Kubernetes学习笔记

YAML模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

K8S的控制器

控制器的种类可以在kubernetes/pkg/controller/目录下查看,包括但不限于:

  • deployment
  • job
  • podautoscaler
  • cronjob
  • statefulset
  • daemon
  • volume
  • namespace
  • replicaset

常用命令:

  • kubectl create -f nginx-deployment.yaml

通过yaml文件创建新的容器,不建议使用

  • kubectl replace -f nginx-deployment.yaml

通过yaml文件更新容器,比如升级一个新版本,不建议使用

  • kubectl apply -f nginx-deployment.yaml

根据yaml文件的内容变化,自动进行具体的处理,包含了create和replace的功能,建议使用

  • kubectl get pods -l app=nginx

查看pods的运行情况,在命令行中,所有 key-value 格式的参数,都使用“=”而非“:”表示。使用-o yaml可以输出当前实际运行的配置内容

  • kubectl describe pod nginx-deployment-67594d6bf6-9gdvr

查看pod对象的具体细节

  • kubectl exec -it nginx-deployment-5c678cfb6d-lg9lw – /bin/bash

进入到pod中

  • kubectl delete -f nginx-deployment.yaml

删除指定容器

  • kubectl scale deployment nginx-deployment –replicas=4

deployment扩缩容

  • kubectl rollout status deployment/nginx-deployment

实时查看 Deployment 对象的状态变化

  • kubectl edit deployment/nginx-deployment

更新deployment的字段,其实质是下载API对象到本地修改完后再进行提交

  • kubectl set image deployment/nginx-deployment nginx=nginx:1.8.0

直接修改deployment所使用的镜像,无需像edit一样再修改文本

  • kubectl rollout undo deployment/nginx-deployment

回滚deployment到上一个版本,--to-revision=2参数可以指定回滚的版本

  • kubectl rollout history deployment/nginx-deployment

查看deployment对应的变更历史,需在创建时开启--record参数

  • kubectl rollout pause deployment/nginx-deployment
  • kubectl rollout resume deploy/nginx-deployment

在pause和resume之间进行的变更,只会触发一次deployment的“滚动更新”

Deployment与Pod的关系

Deployment控制ReplicaSet(版本),ReplicaSet控制Pod(副本数),因此一个ReplicaSet代表着Pod的一个版本,Pod升级的过程也就是新旧ReplicaSet交替的过程。

Pod中的字段定义

  • NodeSelector:是一个供用户将 Pod 与 Node 进行绑定的字段
  • NodeName:一旦 Pod 的这个字段被赋值,Kubernetes项目就会认为这个Pod已经经过了调度,调度的结果就是赋值的节点名字。所以,这个字段一般由调度器负责设置,但用户也可以设置它来“骗过”调度器,当然这个做法一般是在测试或者调试的时候才会用到。
  • HostAliases:定义了 Pod 的 hosts 文件(比如 /etc/hosts)里的内容

Pod状态

  1. Pending:这个状态意味着,Pod 的 YAML 文件已经提交给了 Kubernetes,API 对象已经被创建并保存在 Etcd 当中。但是,这个 Pod里有些容器因为某种原因而不能被顺利创建。比如,调度不成功。

  2. Running:这个状态下,Pod 已经调度成功,跟一个具体的节点绑定。它包含的容器都已经创建成功,并且至少有一个正在运行中。

  3. Succeeded:这个状态意味着,Pod 里的所有容器都正常运行完毕,并且已经退出了。这种情况在运行一次性任务时最为常见。

  4. Failed:这个状态下,Pod 里至少有一个容器以不正常的状态(非 0 的返回码)退出。这个状态的出现,意味着你得想办法 Debug 这个容器的应用,比如查看 Pod 的 Events 和日志。

  5. Unknown:这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。

pod的Conditions值包括:PodScheduled、Ready、Initialized,以及 Unschedulable。

Projected Volume

1. Secret

把Pod想要访问的加密数据,存放到Etcd中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: Pod
metadata:
name: test-projected-volume
spec:
containers:
- name: test-secret-volume
image: busybox
args:
- sleep
- "86400"
volumeMounts:
- name: mysql-cred
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: mysql-cred
projected:
sources:
- secret:
name: user
- secret:
name: pass

创建secret可使用如下操作

1
2
3
4
5
6
7
$ cat ./username.txt
admin
$ cat ./password.txt
c1oudc0w!

$ kubectl create secret generic user --from-file=./username.txt
$ kubectl create secret generic pass --from-file=./password.txt

或者直接写在YAML中

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
user: YWRtaW4=
pass: MWYyZDFlMmU2N2Rm

这里的user和pass都必须经过Base64转码,如

1
2
3
4
echo -n 'admin' | base64
YWRtaW4=
$ echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm
2. ConfigMap

用法与secret几乎一致,区别是ConfigMap存储的内容应该是不需要加密的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# .properties 文件的内容
$ cat example/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

# 从.properties文件创建ConfigMap
$ kubectl create configmap ui-config --from-file=example/ui.properties

# 查看这个 ConfigMap 里保存的信息 (data)
$ kubectl get configmaps ui-config -o yaml
apiVersion: v1
data:
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
name: ui-config
...

可以直接通过配置文件生成ConfigMap

3. Downward API

可用于打印一些容器相关的静态信息,如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1. 使用 fieldRef 可以声明使用:
spec.nodeName - 宿主机名字
status.hostIP - 宿主机 IP
metadata.name - Pod 的名字
metadata.namespace - Pod 的 Namespace
status.podIP - Pod 的 IP
spec.serviceAccountName - Pod 的 Service Account 的名字
metadata.uid - Pod 的 UID
metadata.labels['<KEY>'] - 指定 <KEY> 的 Label 值
metadata.annotations['<KEY>'] - 指定 <KEY> 的 Annotation 值
metadata.labels - Pod 的所有 Label
metadata.annotations - Pod 的所有 Annotation

2. 使用 resourceFieldRef 可以声明使用:
容器的 CPU limit
容器的 CPU request
容器的 memory limit
容器的 memory request

具体用法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: v1
kind: Pod
metadata:
name: test-downwardapi-volume
labels:
zone: us-est-coast
cluster: test-cluster1
rack: rack-22
spec:
containers:
- name: client-container
image: k8s.gcr.io/busybox
command: ["sh", "-c"]
args:
- while true; do
if [[ -e /etc/podinfo/labels ]]; then
echo -en '\n\n'; cat /etc/podinfo/labels; fi;
sleep 5;
done;
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
readOnly: false
volumes:
- name: podinfo
projected:
sources:
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
1
2
3
4
5
kubectl create -f dapi-volume.yaml
$ kubectl logs test-downwardapi-volume
cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"

容器启动后可通过logs查看输出信息

4. ServiceAccountToken

这是一种特殊的secret,用于进行权限分配。

为了方便使用,Kubernetes提供了一个默认“服务账户”(default Service Account)。任何一个运行在Kubernetes里的Pod,都可以直接使用这个默认的 Service Account,而无需显示地声明挂载它。

健康检查livenessProbe

  1. 通过命令检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: test-liveness-exec
spec:
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
  1. 通过http接口检查
1
2
3
4
5
6
7
8
9
10
...
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
  1. 通过tcp检查端口
1
2
3
4
5
6
...
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20

健康检查失败时,会触发Kubernetes里的Pod恢复机制,也叫restartPolicy,该字段有三种定义,分别是:

  • Always:在任何情况下,只要容器不在运行状态,就自动重启容器;
  • OnFailure: 只在容器 异常时才自动重启容器;
  • Never: 从来不重启容器。

一般默认使用的是Always,值得一提的是,这里的重启其实是创建新的容器,但这个pod永远会在同一个Node(宿主机)上,除非绑定关系发生了变化(pod.spec.node字段被修改)。或者也可以通过Deployment来管理pod。

service

service有以下类型,分别是ClusterIP(默认)、NodePort、LoadBalancer和ExternalName

可以通过kubectl get endpoints 查看所有service对应的endpoints,这里的endpoints即是service对应的pod列表

service的访问机制
  1. 通过service的虚拟IP的方式访问
  2. 通过service的DNS方式,格式为..svc.cluster.local,该方式只暴露一条pod记录
  3. 通过headless service方式访问,该情况下clusterIP 字段的值是:None,该service不会被分配VIP,而是以DNS解析记录的方式暴露所有对应的pod信息,格式为...svc.cluster.local

service的DNS记录检查可以通过创建一个临时busybox的pod

kubectl run -i –tty –image busybox:1.28.4 dns-test –restart=Never –rm /bin/sh

该pod为临时pod,退出后即被销毁,在其内部通过nslookup指令可以解析对应域名

1
2
3
4
5
6
/ # nslookup  nginx-service
Server: 10.43.0.10
Address 1: 10.43.0.10 kube-dns.kube-system.svc.cluster.local

Name: nginx-service
Address 1: 10.43.84.254 nginx-service.hmall.svc.cluster.local

注:当在同一namespace下时,可以直接通过访问,否则需要.形式访问