资源对象的配置格式
-
API server接受和返回的所有JSON对象都遵循同一个模式,它们都具有“kind”和“apiVersion”字段,用于标识对象所属的资源类型、API群组及相关的版本
-
大多数的对象或列表类型的资源还需要具有三个嵌套型的字段
metadata、spec和status- metadata字段为资源提供元数据信息,例如名称、隶属的名称空间和标签等;
- spec用于定义用户期望的状态,不同的资源类型,其状态的意义各有不同,例如Pod资源最为核心的功能在于运行容器;
- status则记录着活动对象的当前状态信息,它由Kubernetes系统自行维护,对用户来说为只读字段;
- “kubectl api-resources”命令可以获取集群支持使用的所有资源类型
资源对象的管理
默认情况下,k8s集群没有运行任何资源,那资源从何而来?可通过kubectl客户端工具控制的,比如kubectl create等。但kubectl的命令可分为三类:
- 陈述式命令:使用run、expose、delete和get等命令,它们直接作用于Kubernetes系统上的活动对象,简单易用,但不支持代码复用、修改复审及审计日志等功能,这些功能的实现通常要依赖于资源配置文件中,这些文件也被称为资源清单。
- 陈述式对象配置:使用yaml/json格式定义资源的期望状态。
- 声明式对象配置:使用apply的方式,完成增删改的所有操作,一般是增和改;而删除使用delete 。
陈述式对象配置
使用资源清单创建名称空间,namespace属于集群级别的资源
ilinux@master:~/manifests/basic$ kubectl get ns default -o yaml --export > develop-ns.yaml
## 修改
ilinux@master:~/manifests/basic$ cat develop-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: develop
selfLink: /api/v1/namespaces/develop
ilinux@master:~/manifests/basic$ kubectl create -f develop-ns.yaml
namespace/develop created
上述称为陈述式配置文件
声明式对象配置
ilinux@master:~/manifests/basic$ kubectl apply -f prod-ns.yaml
namespace/prod created
ilinux@master:~/manifests/basic$ cat prod-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: prod
声明式操作,此时如果修改了配置文件,再apply一次即可。而陈述式配置 create只能一次。
声明式操作apply还可以把目录下的所有yaml文件直接应用,因此推荐使用。它是最好的k8s api功能接口:声明式接口。
一个资源到底应该使用哪个资源的哪个群组?可通过kubernetes的文档查询:
ilinux@master:~/manifests/basic$ kubectl explain namespace
KIND: Namespace
VERSION: v1
...
创建自主式pod,不被任何控制器管理的pod
ilinux@master:~/manifests/basic$ kubectl apply -f myapp-pod.yaml
pod/myapp created
ilinux@master:~/manifests/basic$ cat myapp-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp
namespace: develop
labels:
app: myapp
spec:
containers:
- image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
name: myapp
说明:
- containers容器是个列表,因此使用横线。因为一个pod可能存在多个容器,因此必须使用数组或列表。
- imagePullPolicy:IfNotPresent/Always/Never,注意:如果image指定的标签为latest,则IfNotPresent的默认值实际上是Always,因为本地的镜像不一定是latest,因此都会从互联网下载。而指定了其他标签时,才是它本意。
可以使用帮助kubectl expain的输出帮助来写pod的资源清单,而无需借助模板,比如:
ilinux@master:~/manifests/basic$ cat bbox-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-demo
namespace: prod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
- name: bbox
image: busybox:latest
command: ["/bin/sh","-c","sleep 3600"]
其中 command: <[]string 字符串列表>,也可以写成如下形式:
- /bin/sh
- -c
- “sleep 3600”
ilinux@master:~/manifests/basic$ kubectl get pods -n prod
NAME READY STATUS RESTARTS AGE
app-demo 2/2 Running 0 56s
尝试链接busybox,然后通过busybox访问myapp:
# 如果一个pod有多个容器,需要使用-c指定容器
ilinux@master:~/manifests/basic$ kubectl exec app-demo -c bbox -it -n prod -- /bin/sh
# 监听了80端口,因为两个容器共享了网络名称空间
/ # netstat -tanl
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
# 通过lo访问另外一个容器提供的服务
/ # wget -O - -q 127.0.0.1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
查看指定pod指定容器的日志:
ilinux@master:~/manifests.raw/demo$ kubectl logs app-demo -n prod -c myapp
127.0.0.1 - - [18/Aug/2020:05:42:19 +0000] "GET / HTTP/1.1" 200 65 "-" "Wget" "-"
定义pod时,可共享宿主机的网络名称空间。不过此操作有风险,一般不使用。资源清单中设置属性:
...
spec:
hostNetwork: true
containers:
- name: myapp
...
分配的地址为所在节点的IP地址,可在外部访问。但存在端口冲突的可能:
ilinux@master:~/manifests/basic$ kubectl get pods -o wide -n prod
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app-demo 2/2 Running 0 51s 192.168.2.12 node2 <none> <none>
ports 指定容器暴露的端口
ilinux@master:~$ kubectl explain pods.spec.containers.ports.containerPort
apiVersion: v1
kind: Pod
metadata:
name: app-demo
namespace: prod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
- name: bbox
image: busybox:latest
command: ["/bin/sh","-c","sleep 3600"]
ports:
- protocol: TCP
containerPort: 80
name: http
hostPort: 8080
hostPort:实际上宿主机定义了DNAT,通过访问宿主机的端口,去访问容器端口。此处仅仅在宿主机定义,而不是所有node都可以访问到。
而nodePort类型的service,则访问任意宿主机都可访问到Pod地址。