pod
pause 容器
也叫 Infra 容器
对于 Pod 里的容器 A 和容器 B 来说:
- 它们可以直接使用 localhost 进行通信;
- 它们看到的网络设备跟 Infra 容器看到的完全一样;
- 一个 Pod 只有一个 IP 地址,也就是这个 Pod 的 Network Namespace 对应的 IP 地址;
- 当然,其他的所有网络资源,都是一个 Pod 一份,并且被该 Pod 中的所有容器共享;
- pod 的生命周期只跟 Infra 容器一致,而与容器 A 和 B 无关。
pause容器作用
- 扮演Pid=1的,回收僵尸进程
- 基于Linux的namespace的共享
Kubernetes 项目里,Infra 容器一定要占用极少的资源,所以它使用的是一个非常特殊的镜像,叫作:k8s.gcr.io/pause。这个镜像是一个用汇编语言编写的、永远处于“暂停”状态的容器,解压后的大小也只有 100~200 KB 左右。
而在 Infra 容器“Hold 住”Network Namespace 后,用户容器就可以加入到 Infra 容器的 Network Namespace 当中了
多容器进入
1kubectl exec -it xxx -c 容器名 -- sh
挂载主机目录hostPath
https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/
1apiVersion: v1
2kind: Pod
3metadata:
4 name: test-pd
5spec:
6 containers:
7 - image: registry.k8s.io/test-webserver
8 name: test-container
9 volumeMounts:
10 - mountPath: /test-pd
11 name: test-volume
12 volumes:
13 - name: test-volume
14 hostPath:
15 # 宿主上目录位置
16 path: /data
17 # 此字段为可选
18 type: Directory
pod中的2个容器共享文件夹
同一个pod内的容器都能读写EmptyDir中 文件。常用于临时空间、多容器共享,如日志或者tmp文件需要的临时目录
两个容器分别写入挂载点 volumeMounts
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myngx
5spec:
6 selector:
7 matchLabels:
8 app: nginx
9 replicas: 1
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 containers:
16 - name: ngx
17 image: nginx:1.18-alpine
18 imagePullPolicy: IfNotPresent
19 volumeMounts:
20 - name: sharedata
21 mountPath: /data
22 - name: alpine
23 image: alpine:3.12
24 imagePullPolicy: IfNotPresent
25 command: ["sh","-c","echo this is alpine && sleep 36000"]
26 volumeMounts:
27 - name: sharedata
28 mountPath: /data
29 volumes:
30 - name: sharedata
31 emptyDir: {}
init容器的基本使用、sidecar模式
https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/init-containers/
Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本
Init 容器与普通的容器非常像,除了如下两点:
它们总是运行到完成。
每个都必须在下一个启动之前成功完成。
如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 “Never”,Kubernetes 不会重新启动 Pod。
1apiVersion: v1
2kind: Pod
3metadata:
4 name: javaweb-2
5spec:
6 initContainers:
7 - image: geektime/sample:v2
8 name: war
9 command: ["cp", "/sample.war", "/app"]
10 volumeMounts:
11 - mountPath: /app
12 name: app-volume
13 containers:
14 - image: geektime/tomcat:7.0
15 name: tomcat
16 command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
17 volumeMounts:
18 - mountPath: /root/apache-tomcat-7.0.42-v2/webapps
19 name: app-volume
20 ports:
21 - containerPort: 8080
22 hostPort: 8001
23 volumes:
24 - name: app-volume
25 emptyDir: {}
像这样,我们就用一种“组合”方式,解决了 WAR 包与 Tomcat 容器之间耦合关系的问题。
实际上,这个所谓的“组合”操作,正是容器设计模式里最常用的一种模式,它的名字叫:sidecar。
sidecar 指的就是我们可以在一个 Pod 中,启动一个辅助容器,来完成一些独立于主进程(主容器)之外的工作。
在我们的这个应用 Pod 中,Tomcat 容器是我们要使用的主容器,而 WAR 包容器的存在,只是为了给它提供一个 WAR 包而已。所以,我们用 Init Container 的方式优先运行 WAR 包容器,扮演了一个 sidecar 的角色。
资源限制
1apiVersion: v1
2kind: Pod
3metadata:
4 name: busybox
5 namespace: dev
6 labels:
7 app: busybox
8spec:
9 containers:
10 - image: busybox
11 name: busybox
12 imagePullPolicy: IfNotPresent
13 env:
14 - name: app
15 value: busybox
16 # 终端
17 tty: true
18 # 拥有宿主机权限
19 securityContext:
20 privileged: true
21 workingDir: /test
22 command: ["/bin/sh"]
23 args: ["-c","while true; do echo hello;sleep 10; done"]
24 resources:
25 requests:
26 # 100mb
27 memory: "100Mi"
28 # 1核心 = 1000m
29 cpu: "1000m"
30 limits:
31 memory: "200Mi"
32 cpu: "1000m"
网络
1apiVersion: v1
2kind: Pod
3metadata:
4 name: nginx
5 namespace: dev
6 labels:
7 app: nginx
8spec:
9 # hostNetwork: true
10 # 可选值 Default|ClusterFirst|ClusterFirstWithHostNet|None
11 dnsPolicy: "Default"
12 # dns配置
13 dnsConfig:
14 nameservers:
15 - 8.8.8.8
16 #域名映射
17 hostAliases:
18 - ip: 192.168.56.80
19 hostnames:
20 - "foo.local"
21 - "bar.local"
22 containers:
23 - name: nginx
24 image: nginx:1.17.1
25 imagePullPolicy: IfNotPresent
26 ports:
27 - name: nginx-port
28 containerPort: 80
29 protocol: TCP
30 hostPort: 8080 # 如果使用 hostNetwork 则这里不生效
pod健康检查
每个容器三种探针(Probe)
-
启动探针 一次性成功探针。只要启动成功了
- kubelet 使用启动探针,来检测应用是否已经启动。如果启动就可以进行后续的探测检 查。慢容器一定指定启动探针。一直在等待启动
- 启动探针 成功以后就不用了,剩下存活探针和就绪探针持续运行
-
存活探针
- kubelet 使用存活探针,来检测容器是否正常存活。(有些容器可能产生死锁【应用程序 在运行,但是无法继续执行后面的步骤】), 如果检测失败就会**重新启动这个容器 **
- initialDelaySeconds: 3600(长了导致可能应用一段时间不可用) 5(短了陷入无限启动循环)
-
就绪探针
- kubelet 使用就绪探针,来检测容器是否准备好了可以接收流量。当一个 Pod 内的所有容器都准备好了,才能把这个 Pod 看作就绪了。用途就是:Service后端负载均衡多个 Pod,如果某个Pod还没就绪,就会从service负载均衡里面剔除
谁利用这些探针探测?
kubelet会主动按照配置给Pod里面的所有容器发送响应的探测请求
Probe 配置项
1exec、httpGet、tcpSocket 【那种方式探测】
2
3exec 启动一个命令 返回0 才算成功, 其他算失败
4
5initialDelaySeconds 20 容器启动后指定多少秒后 才开始探测
6periodSeconds 每隔多少秒运行
7successThreshold 1 探测器在失败后,被视为成功的最小连续成功数。默认值是 1。
8 存活和启动探针的这个值必须是 1。最小值是 1。 连续成功1次就算成功。 如果是5 那么必须连续成功5次才行
9
10failureThreshold 2 几次失败才算真失败
11
12terminationGracePeriodSeconds
13timeoutSeconds <integer>
拉取私有镜像
创建一个Secret对象来存储认证信息。可以使用以下命令创建一个基于用户名和密码的Secret
1$ kubectl create secret docker-registry mysecret --docker-server=<私有镜像地址> --docker-username=<用户名> --docker-password=<密码> -n=命名空间
将这个Secret应用到Pod配置文件中的imagePullSecrets字段中。示例如下:
1apiVersion: v1
2kind: Pod
3metadata:
4 name: mypod
5spec:
6 containers:
7 - name: mycontainer
8 image: <私有镜像地址>/<镜像名称>:<标签>
9 imagePullSecrets:
10 - name: mysecret
pod 的钩子函数
pod 钩子函数 主要有 2 个 postStart 和preStop 。postStart 在容器创建之后执行,preStop则在容器销毁之前执行。
1apiVersion: v1
2kind: Namespace
3metadata:
4 name: dev
5---
6apiVersion: v1
7kind: Pod
8metadata:
9 name: nginx-gouzi
10 namespace: dev
11 labels:
12 app: nginx
13spec:
14 containers:
15 # 可以有多个容器
16 - name: nginx
17 image: nginx
18 imagePullPolicy: IfNotPresent
19 lifecycle:
20 postStart:
21 exec:
22 command: [ "/bin/sh","-c","echo 'hello world...' > /opt/demo.txt" ]
23 preStop:
24 exec:
25 command: [ "/usr/sbin/nginx","-s","quit" ]
调度
kube-scheduler 给一个 Pod 做调度选择时包含两个步骤:
- 过滤
- 打分
Pod 的调度
- 与节点标签匹配的 nodeSelector
- 亲和性与反亲和性
- nodeName 字段
打标签
1kubectl get nodes --show-labels
2kubectl label node `node_name` `key=value`
3kubectl label node `node_name` `key`- # 取消label
污点(node)、容忍(pod)
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/
亲和和反亲和
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/
configMap
ConfigMap 是一种 API 对象,用来将非机密性的数据保存到健值对中。使用时可以用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap 将您的环境配置信息和 容器镜像 解耦,便于应用配置的修改。当您需要储存机密信息时可以使用 Secret 对象。
使用的四个场景
1、 容器 entrypoint 的命令行参数
2、 容器的环境变量
3、 映射成文件
4、 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
获取列表
1kubectl get cm
容器环境变量引用
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: mycm
5data:
6 # 每一个键对应一个简单的值,以字符串的形式体现
7 username: "crmao"
8 userage: "30"
9 # 多行模式,下面只是字符串
10 user.info: |
11 name=mao
12 age=19
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myngx
5spec:
6 selector:
7 matchLabels:
8 app: nginx
9 replicas: 1
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 containers:
16 - name: ngx
17 image: nginx:1.18-alpine
18 imagePullPolicy: IfNotPresent
19 env:
20 - name: TEST
21 value: testvalue
22 - name: USERNAME
23 valueFrom:
24 configMapKeyRef:
25 name: mycm # ConfigMap的名称
26 key: username # 需要取值的键
映射成容器中的单文件
https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myngx
5spec:
6 selector:
7 matchLabels:
8 app: nginx
9 replicas: 1
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 containers:
16 - name: ngx
17 image: nginx:1.18-alpine
18 imagePullPolicy: IfNotPresent
19 volumeMounts:
20 - name: cmdata
21 mountPath: /data
22 env:
23 - name: TEST
24 value: testvalue
25 - name: USERNAME
26 valueFrom:
27 configMapKeyRef:
28 name: mycm # ConfigMap的名称
29 key: username # 需要取值的键
30 volumes:
31 - name: cmdata
32 configMap:
33 name: mycm
34 items:
35 - key: user.info
36 path: user.txt # 那么在ngx容器中 /data目录下会存在 user.txt文件 内容是 configmap 键为user.info 的值
subpath
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myngx
5spec:
6 selector:
7 matchLabels:
8 app: nginx
9 replicas: 1
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 containers:
16 - name: ngx
17 image: nginx:1.18-alpine
18 imagePullPolicy: IfNotPresent
19 volumeMounts:
20 - name: cmdata
21 mountPath: /data/user.txt
22 subPath: user.info
23 env:
24 - name: TEST
25 value: testvalue
26 - name: USERNAME
27 valueFrom:
28 configMapKeyRef:
29 name: mycm # ConfigMap的名称
30 key: username # 需要取值的键
31 volumes:
32 - name: cmdata
33 configMap:
34 defaultMode: 0655
35 name: mycm
36# items:
37# - key: user.info
38# path: user.txt
k8s内置类型
Kubernetes提供若干种内置的类型,用于一些常见的使用场景。 针对这些类型,Kubernetes所执行的合法性检查操作以及对其所实施的限制各不相同。
内置类型 | 用法 |
---|---|
Opaque | 用户定义的任意数据 |
kubernetes.io/service-account-token | 服务账号令牌 |
kubernetes.io/dockercfg | ~/.dockercfg 文件的序列化形式 |
kubernetes.io/dockerconfigjson | ~/.docker/config.json 文件的序列化形式 |
kubernetes.io/basic-auth | 用于基本身份认证的凭据 |
kubernetes.io/ssh-auth | 用于 SSH 身份认证的凭据 |
kubernetes.io/tls | 用于 TLS 客户端或者服务器端的数据 |
bootstrap.kubernetes.io/token | 启动引导令牌数据 |
secret
Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全和灵活。 参阅 Secret 设计文档 获取更多详细信息。
Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 用户可以创建 Secret,同时系统也创建了一些 Secret。
敏感、少量 ,安全和灵活
类型 : Opaque 用户自定义的类型
https://www.kubernetes.org.cn/secret
1apiVersion: v1
2kind: Secret
3metadata:
4 name: mysecret
5type: Opaque
6data:
7 user: c2hlbnlp
8 pass: MTIzNDU2
1echo -n "123456" | base64
2echo -n "MTIzNDU2" | base64 -d
存储卷管理
EmptyDir
删除Pod时,emptyDir数据同步消失
1# 缓存数据,可以让多个容器共享数据
2# 删除Pod时,emptyDir数据同步消失
3# 定义initContainer->下载数据到emptyDir->在container挂载emptyDir,能看数据共享
4apiVersion: v1
5kind: Pod
6metadata:
7 name: busybox
8 namespace: dev
9 labels:
10 app: busybox
11spec:
12 nodeName: k8snode1
13 initContainers:
14 - name: download
15 image: busybox
16 command: ['/bin/sh','-c','echo hello > /workdir/index.html']
17 volumeMounts:
18 - name: workdir
19 mountPath: /workdir
20 containers:
21 - name: web
22 image: nginx
23 ports:
24 - containerPort: 80
25 hostPort: 8080
26 volumeMounts:
27 - name: workdir
28 mountPath: /usr/share/nginx/html
29 volumes:
30 - name: workdir
31 emptyDir: {}
1root@k8smaster:~# curl http://192.168.56.81:8080
2hello
hostPath
挂载到宿主机
type: DirectoryOrCreate | Directory | File | FileOrCreate | Socket | ""
Directory : 没有目录会会报错
1# docker -v 参数等效
2apiVersion: v1
3kind: Pod
4metadata:
5 name: busybox
6 namespace: dev
7 labels:
8 app: busybox
9spec:
10 nodeName: k8snode1
11 containers:
12 - name: web
13 image: nginx
14 ports:
15 - containerPort: 80
16 hostPort: 8080
17 volumeMounts:
18 - name: workdir
19 mountPath: /usr/share/nginx/html
20 volumes:
21 - name: workdir
22 hostPath:
23 # DirectoryOrCreate | Directory | File | FileOrCreate | Socket | ""
24 type: DirectoryOrCreate
25 path: /workdir2
在k8snode1机器上查看
1docker inspect `CONTAINER ID`
downward
作用: 将pod的定义信息(metadata信息)挂载到容器内
1# 将pod的定义信息(metadata信息)挂载到容器内
2apiVersion: v1
3kind: Pod
4metadata:
5 name: busybox
6 namespace: dev
7 labels:
8 app: busybox
9spec:
10 nodeName: k8snode1
11 containers:
12 - name: web
13 image: nginx
14 ports:
15 - containerPort: 80
16 hostPort: 8080
17 env:
18 - name: MY_NODE_NAME
19 valueFrom:
20 fieldRef:
21 fieldPath: spec.nodeName
22 # podIP nodeIP sa
23 volumeMounts:
24 - name: workdir
25 mountPath: /usr/share/nginx/html
26 volumes:
27 - name: workdir
28 downwardAPI:
29 items:
30 - path: podname.html
31 fieldRef:
32 fieldPath: metadata.name
查看结果
1kubectl exec -it busybox -n dev -- sh
2printenv
3# 有 MY_NODE_NAME=k8snode1
4root@k8smaster:~# curl http://192.168.56.81:8080/podname.html
5busybox
configmap
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: testcm
5 namespace: test
6data:
7 db_name: mysql
8 db_name1: mysql1
1# 将configMap的所有的数据挂载到pod的容器内
2apiVersion: v1
3kind: Pod
4metadata:
5 name: busybox
6 namespace: dev
7 labels:
8 app: busybox
9spec:
10 nodeName: k8snode1
11 containers:
12 - name: web
13 image: nginx
14 imagePullPolicy: IfNotPresent
15 ports:
16 - containerPort: 80
17 hostPort: 8080
18 volumeMounts:
19 - name: workdir
20 mountPath: /usr/share/nginx/html
21 volumes:
22 - name: workdir
23 configMap:
24 name: testcm
25 optional: true
进入pod,/usr/share/nginx/html下会多出个文件对应key的名称。
secret
跟configmap 类似
进入pod,/usr/share/nginx/html下会多出个文件对应key的名称。
1apiVersion: v1
2kind: Secret
3metadata:
4 name: testsec
5 namespace: dev
6 labels:
7 secret: testsec
8type: Opaque
9data:
10 db_name: dGVzdGRiMgo=
11 db_host: MTI3LjAuMC4yCg==
12---
13# 将configMap的所有的数据挂载到pod的容器内
14apiVersion: v1
15kind: Pod
16metadata:
17 name: busybox
18 namespace: dev
19 labels:
20 app: busybox
21spec:
22 nodeName: k8snode1
23 containers:
24 - name: web
25 image: nginx
26 imagePullPolicy: IfNotPresent
27 ports:
28 - containerPort: 80
29 hostPort: 8080
30 volumeMounts:
31 - name: workdir
32 mountPath: /usr/share/nginx/html
33 volumes:
34 - name: workdir
35 secret:
36 secretName: testsec
37 optional: true
nfs
nfs安装
1sudo apt -y install nfs-kernel-server # nfs 服务端 安装到集群某一台即可
2sudo apt-get install nfs-common # nfs 客户端 ,每个节点都执行
配置 NFS 访问共享目录
1# 在k8snode1上执行
2sudo mkdir -p /nfs/share
3sudo chmod -R 666 /nfs/share
4sudo vim /etc/exports
5# 加上一行
6/nfs/share 192.168.56.81/24(rw,sync,no_subtree_check,no_root_squash,insecure)
7sudo exportfs -ra # 需要用 exportfs -ra 通知 NFS,让配置生效
8sudo exportfs -v # exportfs -v 验证效果:
9
10
11# 启动nfs
12sudo systemctl start nfs-server
13sudo systemctl enable nfs-server
14sudo systemctl status nfs-server
15
16# showmount 来检查 NFS 的网络挂载情况:
17sudo showmount -e 127.0.0.1
18#Export list for 127.0.0.1:
19#/nfs/share 192.168.56.81/24
k8smaster节点执行
1mkdir -p /tmp/test
2sudo mount -t nfs 192.168.56.81:/nfs/share /tmp/test
3sudo touch /tmp/test/x.yaml
4# 去nfs 服务器验证 /nfs/share 下多出了一个x.yaml
有点问题
1apiVersion: v1
2kind: Pod
3metadata:
4 name: busybox1
5 namespace: dev
6 labels:
7 app: busybox1
8spec:
9 nodeName: k8snode1
10 containers:
11 - name: web
12 image: nginx
13 imagePullPolicy: IfNotPresent
14 ports:
15 - containerPort: 80
16 hostPort: 8080
17 volumeMounts:
18 - name: workdir1
19 mountPath: /usr/share/nginx/html
20 volumes:
21 - name: workdir1
22 nfs:
23 server: 192.168.56.81
24 path: /nfs/share
pv,pvc
手动创建 /nfs/share/pv01 目录
这里pvc 是通过标签 关联到了pv 运行起来后,进入pod ,touch index.html, 对应到k8snode1 ,/nfs/share/pv01 也会多出这个文件,是互通的
pvc 使用来归类的 一个pv 对应一个pvc (实践) 。 pvc这里 跟 ingress class 很像,
1apiVersion: v1
2kind: PersistentVolume
3metadata:
4 name: nfs-pv01
5 namespace: dev
6 labels:
7 pv: nfs-pv01
8spec:
9 capacity:
10 storage: 1Gi
11 accessModes:
12 - ReadWriteOnce
13 #Recycle 删除Pvc同步删除PV | Retain
14 persistentVolumeReclaimPolicy: Retain
15 nfs:
16 path: /nfs/share/pv01
17 server: 192.168.56.81
18 readOnly: false
19---
20apiVersion: v1
21kind: PersistentVolumeClaim
22metadata:
23 name: nfs-pvc01
24 namespace: dev
25 labels:
26 pv: nfs-pvc01
27spec:
28 resources:
29 requests:
30 storage: 500Mi
31 accessModes:
32 - ReadWriteOnce
33 selector:
34 matchLabels:
35 pv: nfs-pv01
36---
37apiVersion: v1
38kind: Pod
39metadata:
40 name: web
41 namespace: dev
42 labels:
43 app: web
44spec:
45 nodeName: k8snode1
46 containers:
47 - name: web
48 image: nginx
49 imagePullPolicy: IfNotPresent
50 ports:
51 - containerPort: 80
52 hostPort: 8080
53 volumeMounts:
54 - name: workdir
55 mountPath: /usr/share/nginx/html
56 volumes:
57 - name: workdir
58 persistentVolumeClaim:
59 claimName: nfs-pvc01
1kubectl get pv ,pvc -n dev
动态存储卷
可以用 StorageClass 绑定一个 Provisioner 对象,而这个 Provisioner 就是一个能够自动管理存储、创建 PV 的应用,代替了原来系统管理员的手工劳动。
NFS Provisoner 安装
1helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
2 helm pull nfs-subdir-external-provisioner/nfs-subdir-external-provisioner
3 tar zxvf nfs-subdir-external-provisioner-4.0.18.tgz
4 cd nfs-subdir-external-provisioner/
5 vim values.yaml
6 # 修改 nfs地址及 镜像仓库(不然拉不下来)
7 #image:
8 #repository: dyrnq/nfs-subdir-external-provisioner
9
10helm install nfs-subdir-external-provisioner . -n kube-system --debug
11helm list -n kube-system
12kubectl get pod -n kube-system | grep nfs
pod指定pvc,pvc指定StorageClass,StorageClass通过 provisioner 自动创建管理pv。
1apiVersion: storage.k8s.io/v1
2kind: StorageClass
3metadata:
4 name: nfs-storage
5 namespace: dev
6provisioner: cluster.local/nfs-subdir-external-provisioner
7#parameters:
8# server: nfs-server.example.com
9# path: /share
10# readOnly: "false"
11mountOptions:
12 - nfsvers=4
13---
14apiVersion: v1
15kind: PersistentVolumeClaim
16metadata:
17 name: nfs-pvc02
18 namespace: dev
19 labels:
20 pvc: nfs-pvc02
21spec:
22 resources:
23 requests:
24 storage: 500Mi
25 accessModes:
26 - ReadWriteOnce
27 storageClassName: nfs-storage
28# selector:
29# matchLabels:
30# pv: nfs-pv01
31---
32apiVersion: v1
33kind: Pod
34metadata:
35 name: web
36 namespace: dev
37 labels:
38 app: web
39spec:
40 nodeName: k8snode1
41 containers:
42 - name: web
43 image: nginx
44 imagePullPolicy: IfNotPresent
45 ports:
46 - containerPort: 80
47 hostPort: 8080
48 volumeMounts:
49 - name: workdir
50 mountPath: /usr/share/nginx/html
51 volumes:
52 - name: workdir
53 persistentVolumeClaim:
54 claimName: nfs-pvc02
PersistentVolume(old)
PersistentVolume:怎么解决数据持久化的难题?
作为存储的抽象,PV 实际上就是一些存储设备、文件系统,比如 Ceph、GlusterFS、NFS,甚至是本地磁盘,管理它们已经超出了 Kubernetes 的能力范围,所以,一般会由系统管理员单独维护,然后再在 Kubernetes 里创建对应的 PV。 要注意的是,PV 属于集群的系统资源,是和 Node 平级的一种对象,Pod 对它没有管理权,只有使用权。
PersistentVolumeClaim,简称 PVC,从名字上看比较好理解,就是用来向 Kubernetes 申请存储资源的。PVC 是给 Pod 使用的对象,它相当于是 Pod 的代理,代表 Pod 向系统申请 PV。一旦资源申请成功,Kubernetes 就会把 PV 和 PVC 关联在一起,这个动作叫做“绑定”(bind)。 但是,系统里的存储资源非常多,如果要 PVC 去直接遍历查找合适的 PV 也很麻烦,所以就要用到 StorageClass。
StorageClass 这个是为了分类,找合适的pv 。
https://github.com/cr-mao/develop/tree/main/k8s/pv
1kubectl apply -f host-path-pv.yml
2kubectl get pv
3
4kubectl apply -f host-path-pvc.yml
5kubectl get pvc
6
7kubectl apply -f host-pvc-pod.yml
服务发现
pod直接 hostPort
我这里只会调度到k8snode1这个节点 http://192.168.56.81:30080
1apiVersion: v1
2kind: Pod
3
4metadata:
5 name: web
6 namespace: dev
7 labels:
8 app: web
9
10spec:
11 containers:
12 - name: web
13 image: nginx
14 imagePullPolicy: IfNotPresent
15 ports:
16 - name: port0
17 containerPort: 80
18 hostPort: 30080
基于service hostport
1apiVersion: v1
2kind: Pod
3
4metadata:
5 name: web
6 namespace: dev
7 labels:
8 app: web
9
10spec:
11 containers:
12 - name: web
13 image: nginx
14 imagePullPolicy: IfNotPresent
15 ports:
16 - name: port0
17 containerPort: 80
18---
19apiVersion: v1
20kind: Service
21metadata:
22 name: svc-web
23 namespace: dev
24spec:
25 # ClusterIP | LoadBalancer |
26 type: NodePort
27 # clusterIP: None
28 selector:
29 app: web
30 ports:
31 - name: http
32 port: 80 # service port
33 targetPort: 80 # 容器nginx 的port
34 nodePort: 30080 #暴露到node的port
loadBalancer
基于这个实现 https://github.com/metallb/metallb
https://metallb.universe.tf/installation/
开启ipvs
1helm repo add metallb https://metallb.github.io/metallb
2helm pull metallb/metallb
3tar zxvf metallb-0.14.3.tgz
4
5cd metallb
6
7 helm install metallb . -n metallb-system --create-namespace --debug
1apiVersion: v1
2kind: Service
3metadata:
4 name: svc-web-lb
5 namespace: test
6spec:
7 # ClusterIP | LoadBalancer |
8 #vip -> real cluster node ip(speaker)
9 type: LoadBalancer
10 # clusterIP: None
11 selector:
12 app: web
13 ports:
14 - name: http
15 port: 80
16 targetPort: 80
17---
18# 我的网络有问题,拉不下来
19apiVersion: metallb.io/v1beta1
20kind: IPAddressPool
21metadata:
22 name: kubeimooc-ippool
23 namespace: metallb-system
24spec:
25 addresses:
26 - 192.168.56.81/32
ingress controller traefik 安装
1kubectl create ns traefik-system
rbac
1kind: ClusterRole
2apiVersion: rbac.authorization.k8s.io/v1
3metadata:
4 name: traefik-role
5 namespace: traefik-system
6rules:
7 - apiGroups:
8 - ""
9 resources:
10 - services
11 - endpoints
12 - secrets
13 verbs:
14 - get
15 - list
16 - watch
17 - apiGroups:
18 - extensions
19 - networking.k8s.io
20 resources:
21 - ingresses
22 - ingressclasses
23 verbs:
24 - get
25 - list
26 - watch
27 - apiGroups:
28 - extensions
29 - networking.k8s.io
30 resources:
31 - ingresses/status
32 verbs:
33 - update
34---
35apiVersion: v1
36kind: ServiceAccount
37metadata:
38 name: traefik-account
39 namespace: traefik-system
40---
41kind: ClusterRoleBinding
42apiVersion: rbac.authorization.k8s.io/v1
43metadata:
44 name: traefik-role-binding
45 namespace: traefik-system
46roleRef:
47 apiGroup: rbac.authorization.k8s.io
48 kind: ClusterRole
49 name: traefik-role
50subjects:
51 - kind: ServiceAccount
52 name: traefik-account
53 namespace: traefik-system
通过daemonset的方式安装traefik
1kind: DaemonSet
2apiVersion: apps/v1
3metadata:
4 name: traefik-deployment
5 namespace: traefik-system
6 labels:
7 app: traefik
8
9spec:
10# replicas: 1
11 selector:
12 matchLabels:
13 app: traefik
14 template:
15 metadata:
16 labels:
17 app: traefik
18 spec:
19 serviceAccountName: traefik-account
20 containers:
21 - name: traefik
22 image: traefik:v2.10
23 imagePullPolicy: IfNotPresent
24 args:
25 - --api.insecure
26 - --providers.kubernetesingress
27 ports:
28 - name: web
29 containerPort: 80
30 hostPort: 80
31 - name: dashboard
32 containerPort: 8080
33 hostPort: 8080
dashboard界面 http://192.168.56.81:8080/
ingress
这里用的是k8s 提供的ingress
一个web的例子
1apiVersion: v1
2kind: Pod
3
4metadata:
5 name: web
6 namespace: dev
7 labels:
8 app: web
9
10spec:
11 containers:
12 - name: web
13 image: nginx
14 imagePullPolicy: IfNotPresent
15 ports:
16 - name: port0
17 containerPort: 80
18---
19apiVersion: v1
20kind: Service
21metadata:
22 name: svc-web
23 namespace: dev
24spec:
25 # ClusterIP | LoadBalancer |
26 type: NodePort
27 # clusterIP: None
28 selector:
29 app: web
30 ports:
31 - name: http
32 port: 80 # service port
33 targetPort: 80 # 容器nginx 的port
34 # nodePort: 30080 #暴露到node的port
35
36---
37apiVersion: networking.k8s.io/v1
38kind: Ingress
39metadata:
40 name: web-ingress
41 namespace: dev
42 annotations:
43 nginx.ingress.kubernetes.io/rewrite-target: /
44spec:
45 # ingressClassName: nginx-example
46 rules:
47 - host: "foo.bar.com"
48 http:
49 paths:
50 - path: /
51 pathType: Prefix
52 backend:
53 service:
54 name: svc-web
55 port:
56 number: 80
本机mac /etc/hosts 添加一行
1 192.168.56.81 foo.bar.com
traefik ingressroute
先把上面的traefik给卸载了。
https://doc.traefik.io/traefik/providers/kubernetes-crd/
Installing Resource Definition and RBAC,在上面增加了crd 和rbac的内容。 以及增加了 providers.kubernetescrd的监听
cd https://github.com/cr-mao/develop/tree/main/k8s/k8s_use/discovery/traefik-advanced
1kubectl apply -f .
把之前的svc,pod 先删了,再看效果(其实没这个必要)
1apiVersion: v1
2kind: Pod
3
4metadata:
5 name: web
6 namespace: dev
7 labels:
8 app: web
9
10spec:
11 containers:
12 - name: web
13 image: nginx
14 imagePullPolicy: IfNotPresent
15 ports:
16 - name: port0
17 containerPort: 80
18---
19apiVersion: v1
20kind: Service
21metadata:
22 name: svc-web
23 namespace: dev
24spec:
25 # ClusterIP | LoadBalancer |
26 type: NodePort
27 # clusterIP: None
28 selector:
29 app: web
30 ports:
31 - name: http
32 port: 80 # service port
33 targetPort: 80 # 容器nginx 的port
34 # nodePort: 30080 #暴露到node的port
35
36---
37apiVersion: traefik.io/v1alpha1
38kind: IngressRoute
39metadata:
40 name: web-ingressroute
41 namespace: dev
42spec:
43 entryPoints:
44 - http
45 routes:
46 - match: Host(`foo.bar.cn`) && PathPrefix(`/`)
47 kind: Rule
48 services:
49 - name: svc-web
50 port: 80
host增加foo.bar.cn 同上面一样,就可以访问nginx页面。
traefik开启https支持、中间件使用
这里已经添加好args,ports https://github.com/cr-mao/develop/tree/main/k8s/k8s_use/discovery/traefik-advanced
这个是demo https://github.com/cr-mao/develop/tree/main/k8s/k8s_use/discovery/traefik_nginx_test
args添加参数
1- --entrypoints.http.address=:80
2- --entrypoints.https.address=:443
ports新增端口映射:
1- name: https
2 containerPort: 443
3 hostPort: 443
生成证书
1openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 3650 -out tls.crt
创建Secret
1kubectl create secret generic test-nginx-cert --from-file=tls.crt --from-file=tls.key -n test
IngressRoute指定secret
1tls:
2 secretName: test-nginx-cert
1cd https://github.com/cr-mao/develop/tree/main/k8s/k8s_use/discovery/traefik_nginx_test
2
3kubectl apply -f .
工作负载
Deployment
可以扩容 缩容, 保证启动多少个pod 。
1# 管理一组Pod
2# replicas 2 -> node01(Pod x 1) node02(Pod x 1)
3# node02(down)
4# wait 30s -> node01(Pod x 2)
5apiVersion: apps/v1
6kind: Deployment
7metadata:
8 name: nginx-deployment
9 namespace: test
10 labels:
11 app: nginx-deployment
12spec:
13 replicas: 2
14 selector:
15 matchLabels:
16 app: nginx-deployment-tp
17 template:
18 metadata:
19 labels:
20 app: nginx-deployment-tp
21 spec:
22 containers:
23 - name: nginx
24 image: nginx
25 imagePullPolicy: IfNotPresent
26 tolerations:
27 - key: "node.kubernetes.io/unreachable"
28 operator: "Exists"
29 effect: "NoExecute"
30 tolerationSeconds: 30
StatefulSet
管理有状态的应用
只使用 Deployment,多个实例之间是无关的,启动的顺序不固定,Pod 的名字、IP 地址、域名也都是完全随机的,这正是“无状态应用”的特点。 但对于“有状态应用”,多个实例之间可能存在依赖关系,比如 master/slave、active/passive,需要依次启动才能保证应用正常运行,外界的客户端也可能要使用固定的网络标识来访问实例,而且这些信息还必须要保证在 Pod 重启后不变。 还有绑定的存储卷。
下面 storageClassName: nfs-client, StorageClass 绑定一个 Provisioner 对象,之前安装了NFS Provisoner
1apiVersion: v1
2kind: Service
3metadata:
4 name: nginx-statefulset-svc
5 namespace: test
6spec:
7 # ClusterIP | LoadBalancer |
8 type: NodePort
9 # headless service
10 # clusterIP: None
11 selector:
12 app: nginx-statefulset-tp
13 ports:
14 - name: http
15 port: 80
16 targetPort: 80
17 nodePort: 30085
18---
19# 管理一组Pod
20# replicas 2
21# 有序性 pod-0 pod-1(pod-0启动之后) -> 停止 pod-0停止(pod-1停止之后)
22# 有状态 id不变 - pvc(绑定pod) -> volumeClaimTemplate
23# 稳定服务发现 service->找到自己想找到的pod
24# curl pod名称.svc名称.命名空间.svc.cluster.local
25apiVersion: apps/v1
26kind: StatefulSet
27metadata:
28 name: nginx-statefulset
29 namespace: test
30 labels:
31 app: nginx-statefulset
32spec:
33 replicas: 2
34 serviceName: nginx-statefulset-svc
35 selector:
36 matchLabels:
37 app: nginx-statefulset-tp
38 template:
39 metadata:
40 labels:
41 app: nginx-statefulset-tp
42 spec:
43 containers:
44 - name: nginx
45 image: nginx
46 imagePullPolicy: IfNotPresent
47 volumeMounts:
48 - name: www
49 mountPath: /usr/share/nginx/html
50 tolerations:
51 - key: "node.kubernetes.io/unreachable"
52 operator: "Exists"
53 effect: "NoExecute"
54 tolerationSeconds: 30
55 volumeClaimTemplates:
56 - metadata:
57 name: www
58 spec:
59 resources:
60 requests:
61 storage: 100Mi
62 accessModes:
63 - ReadWriteOnce
64 storageClassName: nfs-client
pod 名有固定格式的, 集群间pod 可以有固定的服务发现方式进行通信。
1root@k8smaster:/home/www/develop_study/k8s/k8s_install# kubectl get svc -n test
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
3nginx-statefulset-svc ClusterIP None <none> 80/TCP 9h
4
5
6
7root@k8smaster:/home/www/develop_study/k8s/k8s_install# kubectl get pod -n test
8NAME READY STATUS RESTARTS AGE
9nginx-statefulset-0 1/1 Running 0 9h
10nginx-statefulset-1 1/1 Running 0 9h
11
12
13
14root@k8smaster:/home/www/develop_study/k8s/k8s_install# kubectl exec -it nginx-statefulset-0 -n test -- sh
15# cat /etc/hosts
16# Kubernetes-managed hosts file.
17127.0.0.1 localhost
18::1 localhost ip6-localhost ip6-loopback
19fe00::0 ip6-localnet
20fe00::0 ip6-mcastprefix
21fe00::1 ip6-allnodes
22fe00::2 ip6-allrouters
2310.10.249.1 nginx-statefulset-0.nginx-statefulset-svc.test.svc.cluster.localnginx-statefulset-0
24# curl nginx-statefulset-0.nginx-statefulset-svc.test.svc.cluster.local
251111
26# curl nginx-statefulset-0
271111
28# curl nginx-statefulset-1.nginx-statefulset-svc.test.svc.cluster.local
292222
DaemonSet
看门狗,每个节点都会运行, master节点默认不会, 可以搞容忍污点 。 pod删除后,该节点还是再起来。
如kubeproxy(网络转发) 就是一个 DaemonSet, 如监控,日志收集 都适合用 DaemonSet
1
2# 管理一组Pod
3# 每个node上部署一个pod(前提是:不干扰daemonSet调度)
4# node上部署的pod不会被驱逐
5apiVersion: apps/v1
6kind: DaemonSet
7metadata:
8 name: nginx-daemonset
9 namespace: test
10 labels:
11 app: nginx-daemonset
12spec:
13# replicas: 2
14 selector:
15 matchLabels:
16 app: nginx-daemonset-tp
17 template:
18 metadata:
19 labels:
20 app: nginx-daemonset-tp
21 spec:
22 containers:
23 - name: nginx
24 image: nginx
25 imagePullPolicy: IfNotPresent
job
1# 执行一次就结束的Pod
2apiVersion: batch/v1
3kind: Job
4metadata:
5 name: hello
6 namespace: test
7spec:
8 # 尝试backoffLimit+1次 没有成功 则退出Job
9 backoffLimit: 2
10 completions: 3
11 template:
12 spec:
13 # 仅支持 OnFailure Never
14 restartPolicy: Never
15 containers:
16 - name: busybox
17 image: busybox
18 imagePullPolicy: IfNotPresent
19 command:
20 - /bin/sh
21 - -c
22 - echo "Hello Job"
helm
概念
helm是 k8s的包管理器 , helm就是来解决资源整合的问题
好比Linux里面的yum、apt等
helm 拥有一个命令行工具,用于本地开发及管理chart
1、chart :Helm的打包格式叫做chart, 就是一系列文件, 它描述了一组相关的 k8s 集群资源
2、Repoistory :Helm chart 的仓库,Helm 客户端获取存储库中 chart 的索引文件和压缩包
安装
1wget https://get.helm.sh/helm-v3.10.3-linux-amd64.tar.gz
2tar zxvf helm-v3.10.3-linux-amd64.tar.gz
3mv xx/helm /usr/local/bin/helm
仓库
微软的chart仓库 http://mirror.azure.cn/kubernetes/charts/
很流行的 各种charts查询 Kubeapps Hub https://hub.kubeapps.com/charts/incubator
添加仓库
1helm repo add stable http://mirror.azure.cn/kubernetes/charts/
2
3helm repo update
搜索
1
2helm search repo stable/mysql
3
4# xxx 自己取的名字
5helm install xxx stable/mysql
创建
可以看到一堆文件
1helm create mygin
渲染
1helm install my mygin --dry-run --debug
渲染+安装
1helm install my mygin -n myweb
2(helm install [NAME] [CHART] [flags])
1helm list
2helm list -n myweb (命名空间)
3helm uninstall xxx
模板语法简学
values
转义
1container:
2 command: "[\"/app/myserver\"]"
deployment.yaml
with 语法, 前面的-去掉空行
1 workingDir: /app
2 {{- with .Values.container.command }}
3 command: {{ . }}
4 {{- end }}
toYaml 使用yaml格式填充 、 nindent 换行加缩进
1container:
2 command: "[\"/app/gosky\",\"serve\",\"--env=local\"]"
3 volumeMounts:
4 - name: v1
5 mountPath: /app
1 containers:
2 - name: {{ .Chart.Name }}
3 securityContext:
4 {{- toYaml .Values.securityContext | nindent 12 }}
5 image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
6 imagePullPolicy: {{ .Values.image.pullPolicy }}
7 workingDir: /app
8 {{- with .Values.container.command }}
9 command: {{ . }}
10 {{- end }}
11 ports:
12 - name: http
13 containerPort: 7001
14 protocol: TCP
15 volumeMounts: {{ toYaml .Values.container.volumeMounts | nindent 12 }}
16 resources:
17 {{- toYaml .Values.resources | nindent 12 }}
私有镜像
云效 https://repomanage.rdc.aliyun.com/my/helm-repos/namespaces
打包
1helm package mygin
helm push mygin-0.1.0.tgz $NAMESPACE
helm fetch xxx/xxxx 下载chart到本地
提交完成后 刷新repo
helm repo update
helm search repo $NAMESPACE/mygin
安装试一试 helm install xxx $NAMESPACE/mygin -n myweb
更新 help upgrate xxx mygin -n myweb
helm 安装nginx-ingress
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
没科学上网参考下面
1
2helm install my-nginx ingress-nginx/ingress-nginx
3
4不出意外会爆一个错
5k8s.gcr.io/ingress-nginx/controller:v0.40.2 @sha256:46ba23c3fbaafd9e5bd01ea85b2f921d9f2217be082580edc22e6c704a83f02f
6
7
8要么科学上网,要么找个一样的镜像。
9
10docker pull giantswarm/ingress-nginx-controller:v0.40.2
11
12然后改tag
13
14docker tag giantswarm/ingress-nginx-controller:v0.40.2 k8s.gcr.io/ingress-nginx/controller:v0.40.2
15
16删之前的tag
17
18docker rmi giantswarm/ingress-nginx-controller:v0.40.2
下载chart到本地
1helm fetch ingress-nginx/ingress-nginx
2tar zxvf ingress-nginx-4.4.0.tgz
修改部分内容后再次安装 values.yaml
https://github.com/cr-mao/develop/blob/main/k8s/helm/ingress-nginx/values.yaml
1 controller.kind=DaemonSet
2 # 把这个值设置为true:
3 # pod中服务可以使用宿主机的网络接口,宿主主机所在的局域网上所有网络接口都可以访问到该应用程序
4
5 controller.hostNetwork=true
6
7
8 ## Use host ports 80 and 443
9 ## Disabled by default
10 hostPort:
11 # -- Enable 'hostPort' or not
12 enabled: true
13
14
15 # type: LoadBalancer
16 type: NodePort
17
18 ## type: NodePort
19 ## nodePorts:
20 ## http: 32080
21 ## https: 32443
22 ## tcp:
23 ## 8080: 32808
24 nodePorts:
25 http: "32080"
26 https: "32808"
27 tcp: {}
28 udp: {}
29
30
31 admissionWebhooks:
32 annotations: {}
33 # ignore-check.kube-linter.io/no-read-only-rootfs: "This deployment needs write access to root filesystem".
34
35 ## Additional annotations to the admission webhooks.
36 ## These annotations will be added to the ValidatingWebhookConfiguration and
37 ## the Jobs Spec of the admission webhooks.
38 enabled: false
helm install my-nginx ingress-nginx -n my-nginx-ingress
更新命令
helm upgrade my-nginx ingress-nginx -n my-nginx-ingress
安装完只有ingress classes
部署负载均衡 ,service 之前就已经有搞过, ingressClassName 填nginx即可。
ingress.yaml
1apiVersion: networking.k8s.io/v1
2kind: Ingress
3metadata:
4 name: ngx-ing
5
6 # customize the behaviors of nginx
7 annotations:
8 nginx.org/lb-method: round_robin
9
10spec:
11 ingressClassName: nginx
12
13 rules:
14 - host: ngx.test
15 http:
16 paths:
17 - path: /
18 pathType: Prefix
19 backend:
20 service:
21 name: ngx-svc
22 port:
23 number: 80
1curl ngx.test # 看效果即可
k8s认证和授权
用户账号: 集群外部访问时使用的用户,如kubectl 访问集群资源用的 kubernetes-admin (~/.kube/config里),k8s本身不记录这些账号.
创建客户端证书
默认认证方式:客户端证书
1mkdir ua
2cd ua
3# 生成客户端私钥
4openssl genrsa -out client.key 2048
5
6#根据私钥生成csr ,/CN制定用户名为crmao
7openssl req -new -key client.key -out client.csr -subj "/CN=crmao"
8# 根据k8s的CA证书生成我们用户的客户端证书
9sudo openssl x509 -req -in client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out client.crt -days 365
使用证书请求api、设置上下文
其中 可以用 –insecure 代替 –cacert /etc/kubernetes/pki/ca.crt 从而忽略服务端证书验证
1vagrant@k8smaster:~/ua$ curl --cert ./client.crt --key ./client.key --cacert /etc/kubernetes/pki/ca.crt -s https://192.168.56.80:6443/api
2{
3 "kind": "APIVersions",
4 "versions": [
5 "v1"
6 ],
7 "serverAddressByClientCIDRs": [
8 {
9 "clientCIDR": "0.0.0.0/0",
10 "serverAddress": "192.168.56.80:6443"
11 }
12 ]
13}
如果你忘了证书设置的CN(Common name)是啥 可以用下面的命令搞定
1openssl x509 -noout -subject -in client.crt
设置用户到~/.kube/config
1 kubectl config --kubeconfig=/home/vagrant/.kube/config set-credentials crmao --client-certificate=/home/vagrant/ua/client.crt --client-key=/home/vagrant/ua/client.key
创建上下文
1kubectl config --kubeconfig=/home/vagrant/.kube/config set-context user_context --cluster=kubernetes --user=crmao
查看上下文
1vagrant@k8smaster:~/ua$ kubectl config get-contexts
2CURRENT NAME CLUSTER AUTHINFO NAMESPACE
3* kubernetes-admin@kubernetes kubernetes kubernetes-admin
4 user_context kubernetes crmao
指定当前上下文
1kubectl config --kubeconfig=/home/vagrant/.kube/config use-context user_context
2
3# kubectl config get-contexts
Role,Rolebinding
它可以包含一堆权限。用于授予对单个命名空间的资源访问
查看角色
1kubectl get role --all-namespaces
创建角色
1kind: Role
2apiVersion: rbac.authorization.k8s.io/v1
3metadata:
4 namespace: default
5 name: mypod
6rules:
7 - apiGroups: ["*"]
8 resources: ["pods"]
9 verbs: ["get", "watch", "list"]
创建角色绑定
1kubectl create rolebinding mypodbinding -n default --role mypod --user crmao
or
1apiVersion: rbac.authorization.k8s.io/v1
2kind: RoleBinding
3metadata:
4 creationTimestamp: null
5 name: mypodrolebinding
6roleRef:
7 apiGroup: rbac.authorization.k8s.io
8 kind: Role
9 name: mypod
10subjects:
11- apiGroup: rbac.authorization.k8s.io
12 kind: User
13 name: crmao
切成普通用户,查看是否有权限访问pod 权限
1kubectl config use-context user_context # user_context 上面创建的crmao这个用户的上下文。
2kubectl get pod
clusterRole,RoleBinding,ClusterRoleBinding
管理集群中多个 namespace,就需要使用到clusterrole
绑定既可以使用RoleBinding,也可以使用ClusterRoleBinding ( 两者效果不同)
1apiVersion: rbac.authorization.k8s.io/v1
2kind: ClusterRole
3metadata:
4 name: mypod-cluster
5rules:
6 - apiGroups: [ "*" ]
7 resources: [ "pods" ]
8 verbs: [ "get", "watch", "list" ]
9---
10apiVersion: rbac.authorization.k8s.io/v1
11kind: RoleBinding
12metadata:
13 name: mypodrolebinding-cluster
14 # 指定命名空间
15 namespace: kube-system
16roleRef:
17 apiGroup: rbac.authorization.k8s.io
18 kind: ClusterRole
19 name: mypod-cluster
20subjects:
21 - apiGroup: rbac.authorization.k8s.io
22 kind: User
23 name: crmao
那么这个crmao用户就可以看 kube-system命名空间下的 pod 情况了。
配置使用token的方式请求api
head -c 16 /dev/urandom | od -An -t x | tr -d ’ ’ (’ ‘之间有个空格) kubectl config set-credentials crmao –token=4e2f6f4250a43ce94426b6264dad2609
sudo vi /etc/kubernetes/pki/token_auth 塞入如下内容 4e2f6f4250a43ce94426b6264dad2609,crmao,1001
然后是修改api-server启动参数
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
加入 –token-auth-file=/etc/kubernetes/pki/token_auth
1 curl -H "Authorization: Bearer 4e2f6f4250a43ce94426b6264dad2609" https://192.168.56.80:6443/api/v1/namespaces/default/pods --insecure
创建账号ServiceAccount
查看 是这样的:
kubectl get sa -n xxxx (不写-n 就是默认default)
用命令创建一个
1kubectl create serviceaccount mysa
每个namespace都会有一个默认的 default账号,且sa局限在自己所属的namespace中。而UserAccount是可以跨ns的
1vagrant@k8smaster:/etc/kubernetes/pki$ kubectl config get-contexts
2CURRENT NAME CLUSTER AUTHINFO NAMESPACE
3 kubernetes-admin@kubernetes kubernetes kubernetes-admin
4* user_context kubernetes crmao
5vagrant@k8smaster:/etc/kubernetes/pki$ kubectl config use-context kubernetes-admin@kubernetes
6Switched to context "kubernetes-admin@kubernetes".
7vagrant@k8smaster:/etc/kubernetes/pki$ kubectl config get-contexts
8CURRENT NAME CLUSTER AUTHINFO NAMESPACE
9* kubernetes-admin@kubernetes kubernetes kubernetes-admin
10 user_context kubernetes crmao
11vagrant@k8smaster:/etc/kubernetes/pki$ kubectl get sa
12NAME SECRETS AGE
13default 1 121d
1kubectl create serviceaccount mysa
2
3vagrant@k8smaster:/etc/kubernetes/pki$ kubectl get sa
4NAME SECRETS AGE
5default 1 121d
6mysa 1 7s
7
8
9vagrant@k8smaster:/etc/kubernetes/pki$ kubectl describe sa mysa
10Name: mysa
11Namespace: default
12Labels: <none>
13Annotations: <none>
14Image pull secrets: <none>
15Mountable secrets: mysa-token-22j97 (看这个)
16Tokens: mysa-token-22j97
17Events: <none>
18
19
20
21
22kubectl describe secrets mysa-token-22j97
第二种方式创建,用yaml 。
kubectl create serviceaccount mysa -o yaml –dry-run=client
进阶一下,可以这样
kubectl create serviceaccount mysa -o yaml –dry-run=client > mysa.yaml
ServiceAccount赋予权限、外部访问API
账户绑定集群角色
上面创建一个 clusterrole叫做 mypod-cluster 此权限 可以查看 pods列表
安装 解析json的工具
sudo apt install jq
1kubectl create clusterrolebinding mysa-crb --clusterrole=mypod-cluster --serviceaccount=default:mysa
2
3kubectl get sa mysa
4kubectl get sa mysa -o json
5kubectl get sa mysa -o json | jq '.secrets[0].name'
6kubectl get sa mysa -o json | jq -Mr '.secrets[0].name'
k8s的token是base64后的, 要反检一下。
1vagrant@k8smaster:/etc/kubernetes/pki$ kubectl get sa mysa -o json | jq -Mr '.secrets[0].name'
2mysa-token-22j97
3
4
5vagrant@k8smaster:/etc/kubernetes/pki$ kubectl get secret $(kubectl get sa mysa -o json | jq -Mr '.secrets[0].name'
6) -o json | jq -Mr '.data.token' | base64 -d
7
8
9mysatoken=$(kubectl get secret $(kubectl get sa mysa -o json | jq -Mr '.secrets[0].name') -o json | jq -Mr '.data.token' | base64 -d)
10
11
12vagrant@k8smaster:/etc/kubernetes/pki$ kubectl get endpoints
13NAME ENDPOINTS AGE
14kubernetes 192.168.56.80:6443 121d
15ngx-svc 10.10.249.29:80,10.10.249.43:80 88d
16
17vagrant@k8smaster:/etc/kubernetes/pki$ curl -H "Authorization: Bearer $mysatoken" --insecure https://192.168.56.80:6443/api/v1/namespaces/default/pods
SerciveAccount 在POD里访问k8s API(token的方式)
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myngxdepoly
5spec:
6 selector:
7 matchLabels:
8 app: nginx
9 replicas: 1
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 # 加入这个 ,指定账号
16 serviceAccountName: mysa
17 containers:
18 - name: nginxtest
19 image: nginx:alpine
20 imagePullPolicy: IfNotPresent
21 ports:
22 - containerPort: 80
1# 进入pod
2kubectl exec -it myngxdepoly-58bddf9b8d-qmdq7 -- sh
3
4TOKEN=`cat /var/run/secrets/kubernetes.io/serviceaccount/token`
5APISERVER="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT"
6
7 curl --header "Authorization: Bearer $TOKEN" --insecure -s $APISERVER/api
8
9# 我们可以看到 上面是可以的,但下面不可以,因为default账号没有列出pods的权限 ,当上面当yaml 加入了 serviceAccountName: mysa,就可以看pod 列表权限了。
10curl --header "Authorization: Bearer $TOKEN" --insecure -s $APISERVER/api/v1/namespaces/default/pods
serviceAccount 在pod里访问k8s api(证书方式)
更常用的方式是直接用证书 ,上面是用–insecure 跳过了证书
证书的位置在:
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
1#进入pod 执行
2TOKEN=`cat /var/run/secrets/kubernetes.io/serviceaccount/token`
3APISERVER="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT"
4curl --header "Authorization: Bearer $TOKEN" --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt $APISERVER/api/v1/namespaces/default/pods