Fool's blog Fool's blog
首页
  • Ansible
  • Jenkins
  • Docker
  • Kubernetes
  • Linux常用命令
  • Git
  • Nginx
  • PVE
  • Samaba
  • Python
  • Go
GitHub (opens new window)

The Fool

运维萌新
首页
  • Ansible
  • Jenkins
  • Docker
  • Kubernetes
  • Linux常用命令
  • Git
  • Nginx
  • PVE
  • Samaba
  • Python
  • Go
GitHub (opens new window)
  • Docker

  • K8S

    • Kubernetes基础
      • 基础架构
      • 安装部署
        • docker安装
        • cri-docker安装
        • kubectl安装
        • kubeadm、kubelet、kubectl安装
        • 集群初始化
        • 部署网络插件
        • 清理
      • pod
        • initC
        • 钩子
      • pod控制器
        • ReplicationController
        • ReplicaSet
        • Deployment
        • replace和apply 区别
        • 更新策略
        • DaemonSet
        • job
        • cronjob
      • Service
        • ClusterIP
        • NodePort
        • LoadBalancer
        • ExternalName
        • Endpoints
        • publishNotReadyAddresses
      • 存储
        • configMap
        • 环境变量
        • 启动命令
        • 文件
        • 热更新
        • Secret
        • Opaque
        • downward-api
        • Volume
        • emptydir-disk
        • emptydir-mem
        • hostPath
        • PV/PVC
        • StatefulSet部署
        • 安装nfs
        • storageclass
      • 调度器
        • 亲和性(Affinity)
        • 反亲和性
        • 污点容忍
        • 固定节点调度
      • HELM
        • 安装
        • 关键功能
      • ingress-nginx
        • Ingress HTTP 代理访问
        • Ingress HTTPS 代理访问
        • Ingress BasicAuth 代理
        • Ingress-nginx 域名重定向
        • Ingress-nginx 重写
        • Ingress-nginx 默认错误后端
        • Ingress-nginx 定制错误后端
        • Ingress-nginx snippet
        • Ingress-nginx 黑白名单
        • configmap 添加黑名单
        • Ingress-nginx 速率限制
        • ingress-nginx 代理后端 HTTPS 服务
        • ingress-nginx 四层代理
  • 云原生
  • K8S
The Fool
2025-11-02
目录

Kubernetes基础

# Kubernetes基础

Kubernetes 是一个 开源的容器编排平台,用于自动化部署、扩展和管理容器化应用。它最早由 Google 开发,后来捐赠给 CNCF(Cloud Native Computing Foundation) 进行维护。

基础命令

kubectl explain pod.spec
1
kubectl get nodes
1
kubectl get pod -A
1
kubectl get pod -n kube-system
1
kubectl get pod -o wide
1
kebectl get pod -w
1
kubectl get pod podName -o yaml
1
kubectl create -f 1.pod.yaml
1
kubectl exec -it  pod-demo -c myapp-1 -- /bin/bash
1
kubectl  get pod --show-labels
1
get pod -l app
1
kubectl logs pod-demo -c myapp-1
1
kubectl describe pod pod-demo
1
kubectl delete pod --all
1
kubectl delete pod podName
1
kubectl delete svc myservice mydb 
1
kubectl get svc
1
kubectl scale rc rc-demo --replicas=10 
1
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
1
kubectl label pod rc-demo-fwdvk version=v1
1
kubectl diff -f deployment.yaml
1
kubectl replace -f deployment.yaml
1
kubectl apply -f deployment.yaml
1
kubectl create -f deployment.yaml --record
1
kubectl set image deployment/nginx-deployment nginx-container=wangyanglinux/myapp:v2.0
1
kubectL create deployment myapp --image=wangyanglinux/myapp:vl.0 --dry-run -o yaml
1

# 基础架构

参考链接 (opens new window)

1758452538255.png

kube-apiserver:提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制。

etcd:一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后台数据库。

kube-scheduler:kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。

controller manager: 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等。

kubelet:kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。kubelet 接收一组通过各类机制提供给它的 PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。

kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡。

CRI(容器运行时):这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。

Ingress Controller 为服务提供外网入口。

cloud-controller-manager:

cloud provider api:

# 安装部署

# docker安装

bash <(curl -Ls https://raw.githubusercontent.com/zsan1229/install_docker/main/install_docker.sh)
1

# cri-docker安装

wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.17/cri-dockerd_0.3.17.3-0.debian-bookworm_amd64.deb
dpkg -i cri-dockerd_0.3.17.3-0.debian-bookworm_amd64.deb
systemctl enable cri-docker.service  #设置开机自启
systemctl status cri-docker.service  #查看运行状态
1
2
3
4

# kubectl安装

curl -LO https://dl.k8s.io/release/v1.32.0/bin/linux/amd64/kubectl
# 验证安装
curl -LO "https://dl.k8s.io/release/v1.32.0/bin/linux/amd64/kubectl.sha256"
echo "$(cat kubectl.sha256)  kubectl" | sha256sum --check
1
2
3
4

验证用过应该输出

kubectl: OK
1

验证失败时,sha256 将以非零值退出,并打印如下输出:

注意:下载的 kubectl 与校验和文件版本必须相同。

kubectl: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
1
2
install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl   #安装kubectl
kubectl version --client  #验证安装
1
2

正常应输出

Client Version: v1.32.0
Kustomize Version: v5.5.0
1
2

其它安装方式可以参考官网:kubectl (opens new window)

# kubeadm、kubelet、kubectl安装

更新 apt 包索引并安装使用 Kubernetes apt 仓库所需要的包:

sudo apt-get update
# apt-transport-https 可能是一个虚拟包(dummy package);如果是的话,你可以跳过安装这个包
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
1
2
3

下载用于 Kubernetes 软件包仓库的公共签名密钥。所有仓库都使用相同的签名密钥,因此你可以忽略URL中的版本:

# 如果 `/etc/apt/keyrings` 目录不存在,则应在 curl 命令之前创建它,请阅读下面的注释。
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
1
2
3

添加 Kubernetes apt 仓库。 请注意,此仓库仅包含适用于 Kubernetes 1.32 的软件包; 对于其他 Kubernetes 次要版本,则需要更改 URL 中的 Kubernetes 次要版本以匹配你所需的次要版本:

# 此操作会覆盖 /etc/apt/sources.list.d/kubernetes.list 中现存的所有配置。
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
1
2

更新 apt 包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本:

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
1
2
3

# 集群初始化

kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --cri-socket=unix:///var/run/cri-dockerd.sock \
  --apiserver-advertise-address=66.235.170.12
1
2
3
4
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 66.235.170.12:6443 --token umr6tq.as8w3qu1p4kwjo3o \
        --discovery-token-ca-cert-hash sha256:88ef3e471f3e01391f139b4163b1ccc7885cc550f158358174f6029110918ec2 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 加入集群node身份 加上--v=5查看日志
sudo kubeadm join 66.235.170.12:6443 --token aajxe3.d8d5m5o1yvbr5hde \
    --discovery-token-ca-cert-hash sha256:88ef3e471f3e01391f139b4163b1ccc7885cc550f158358174f6029110918ec2 \
    --cri-socket unix:///var/run/cri-dockerd.sock
1
2
3
4

1756561959876.png

# 重新生成token,如果token过期,控制节点上生成
kubeadm token create --print-join-command
1
2

1756562224625.png

# 部署网络插件

kebectl get nodes
1
NAME     STATUS     ROLES           AGE     VERSION
node01   NotReady   control-plane   5m26s   v1.32.8
1
2

这是因为没有部署网络插件造成的。

部署Calico

wget --no-check-certificate https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
ip addr list  # 查看自己的网卡
1
2
vim calico.yaml
插入下面一段
-----
- name: CALICO_IPV4POOL_CIDR
  value: "10.244.0.0/16"
- name: IP_AUTODETECTION_METHOD
  value: "interface=ens160"  

-----
ens160替换为自己的网卡
10.244.0.0/16 替换为自己init的网段
1
2
3
4
5
6
7
8
9
10
11
            # The default IPv4 pool to create on startup if none exists. Pod IPs will be
            # chosen from this range. Changing this value after installation will have
            # no effect. This should fall within `--cluster-cidr`.
            # - name: CALICO_IPV4POOL_CIDR
            #   value: "192.168.0.0/16"
            - name: CALICO_IPV4POOL_CIDR
              value: "10.244.0.0/16"
            - name: IP_AUTODETECTION_METHOD
              value: "interface=ens17"
            # Disable file logging so `kubectl logs` works.
            - name: CALICO_DISABLE_FILE_LOGGING
              value: "true"
1
2
3
4
5
6
7
8
9
10
11
12
kubectl apply -f calico.yaml
1

等待一会

kubectl get nodes 
kubectl get pods --all-namespaces 
1
2
NAME     STATUS   ROLES           AGE     VERSION
node01   Ready    control-plane   5m57s   v1.32.8

NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-689744956f-tk5mc   1/1     Running   0          7m11s
kube-system   calico-node-dv75k                          1/1     Running   0          7m11s
kube-system   coredns-668d6bf9bc-bj62x                   1/1     Running   0          61m
kube-system   coredns-668d6bf9bc-qdfjs                   1/1     Running   0          61m
kube-system   etcd-node01                                1/1     Running   0          61m
kube-system   kube-apiserver-node01                      1/1     Running   0          61m
kube-system   kube-controller-manager-node01             1/1     Running   0          61m
kube-system   kube-proxy-sd8gr                           1/1     Running   0          61m
kube-system   kube-scheduler-node01                      1/1     Running   0          61m
1
2
3
4
5
6
7
8
9
10
11
12
13

# 清理

参考官方文档 (opens new window)

# pod

Pod 是 Kubernetes 中最小的可部署单元。

它本质上是对 一个或多个容器 的抽象封装,这些容器共享 网络、存储 和 运行环境。

poddemo

apiVersion:接口组/版本

kind:类别

metadata:元数据

spec: 期望状态

status: 无需人为编写,由k8s集群生成

apiVersion: v1
kind: Pod
metadata:
    name: pod-demo
    namespace: default
    labels:
        app: myapp
spec:
    containers:
    - name: myapp-1
      image: wangyanglinux/myapp:v1.0
    - name: busybox-1
      image: wangyanglinux/tools:busybox
      command:
        - "/bin/sh"
        - "-c"
        - "sleep 3600"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

pod生命周期

1758538605512.png

# initC

init 容器总是运行到成功完成为止

每个 init 容器都必须在下一个 init 容器启动之前成功完成

检测initC的阻塞性

apiVersion: v1
kind: Pod
metadata:
 name: initc-1
 labels:
   app: initc
spec:
 containers:
 - name: myapp-container
   image: wangyanglinux/tools:busybox
   command: ['sh', '-c', 'echo The app is running! && sleep 3600']
 initContainers:
 - name: init-myservice
   image: wangyanglinux/tools:busybox
   command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
 - name: init-mydb
   image: wangyanglinux/tools:busybox
   command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ kubectl create svc clusterip myservice --tcp=80:80
$ kubectl create svc clusterip mydb --tcp=80:80
1
2

检查 initC 的执行成功

apiVersion: v1
kind: Pod
metadata:
 name: myapp-pod
 labels:
   app: myapp
spec:
 containers:
 - name: myapp
   image: wangyanglinux/myapp:v1.0
 initContainers:
 - name: randexit
   image: wangyanglinux/tools:randexitv1
   args: ["--exitcode=1"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

探针

探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。有三种类型的处理程序:

ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功

TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的

HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的

每次探测都将获得以下三种结果之一:

成功:容器通过了诊断。

失败:容器未通过诊断。

未知:诊断失败,因此不会采取任何行动

三种健康检查探针类型:

startupProbe(启动探针)

用途:检查容器是否已经成功启动

特点:在容器启动阶段执行,成功后不再执行

  • initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位"秒",默认是 0 秒,最小值是 0
  • periodSeconds:执行探测的时间间隔(单位是秒),默认为 10s,单位"秒",最小值是 1
  • timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为 1s,单位"秒",最小值是 1
  • successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为 1。必须为 1 才能激活和启动。最小值为1。
  • failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为 3,最小值为 1。
apiVersion: v1
kind: Pod
metadata:
 name: startupprobe-1
 namespace: default
spec:
 containers:
 - name: myapp-container
   image: wangyanglinux/myapp:v1.0
   imagePullPolicy: IfNotPresent
   ports:
   - name: http
     containerPort: 80
   readinessProbe:
     httpGet:
       port: 80
       path: /index2.html
     initialDelaySeconds: 1
     periodSeconds: 3
   startupProbe:
     httpGet:
       path: /index1.html
       port: 80
     failureThreshold: 30
     periodSeconds: 10
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

livenessProbe(存活探针)

用途:检查容器是否还在正常运行

特点:在整个容器生命周期内定期执行

  • initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位"秒",默认是 0 秒,最小值是 0
  • periodSeconds:执行探测的时间间隔(单位是秒),默认为 10s,单位"秒",最小值是 1
  • timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为 1s,单位"秒",最小值是 1
  • successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为 1。必须为 1 才能激活和启动。最小值为1。
  • failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为 3,最小值为 1。

基于 Exec 方式

apiVersion: v1
kind: Pod
metadata:
 name: liveness-exec-pod
 namespace: default
spec:
 containers:
 - name: liveness-exec-container
   image: wangyanglinux/tools:busybox
   imagePullPolicy: IfNotPresent
   command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep3600"]
   livenessProbe:
     exec:
       command: ["test","-e","/tmp/live"]
     initialDelaySeconds: 1
     periodSeconds: 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

基于 HTTP Get 方式

apiVersion: v1
kind: Pod
metadata:
 name: liveness-httpget-pod
 namespace: default
spec:
 containers:
 - name: liveness-httpget-container
   image: wangyanglinux/myapp:v1.0
   imagePullPolicy: IfNotPresent
   ports:
   - name: http
     containerPort: 80
   livenessProbe:
     httpGet:
       port: 80
       path: /index.html
     initialDelaySeconds: 1
     periodSeconds: 3
     timeoutSeconds: 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

基于 TCP Check 方式

apiVersion: v1
kind: Pod
metadata:
 name: liveness-tcp-pod
spec:
 containers:
 - name: liveness-tcp-container
   image: wangyanglinux/myapp:v1.0
   livenessProbe:
     initialDelaySeconds: 5
     timeoutSeconds: 1
     tcpSocket:
       port: 80
1
2
3
4
5
6
7
8
9
10
11
12
13

readinessProbe(就绪探针)

用途:检查容器是否准备好接收流量

特点:定期检查容器的就绪状态

  • initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位"秒",默认是 0 秒,最小值是 0

  • periodSeconds:执行探测的时间间隔(单位是秒),默认为 10s,单位"秒",最小值是 1

  • timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为 1s,单位"秒",最小值是 1

  • successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为 1。必须为 1 才能激活和启动。最小值为1。

  • failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为 3,最小值为 1。

基于 HTTP Get 方式

apiVersion: v1
kind: Pod
metadata:
 name: readiness-httpget-pod
 namespace: default
 labels:
   app: myapp
   env: test
spec:
 containers:
 - name: readiness-httpget-container
   image: wangyanglinux/myapp:v1.0
   imagePullPolicy: IfNotPresent
   readinessProbe:
     httpGet:
       port: 80
       path: /index1.html
     initialDelaySeconds: 1
     periodSeconds: 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

基于 EXEC 方式

apiVersion: v1
kind: Pod
metadata:
 name: readiness-exec-pod
 namespace: default
spec:
 containers:
 - name: readiness-exec-container
   image: wangyanglinux/tools:busybox
   imagePullPolicy: IfNotPresent
   command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep3600"]
   readinessProbe:
     exec:
       command: ["test","-e","/tmp/live"]
     initialDelaySeconds: 1
     periodSeconds: 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

基于 TCP Check 方式

apiVersion: v1
kind: Pod
metadata:
 name: readiness-tcp-pod
spec:
 containers:
 - name: readiness-exec-container
   image: wangyanglinux/myapp:v1.0
   readinessProbe:
     initialDelaySeconds: 5
     timeoutSeconds: 1
     tcpSocket:
       port: 80
1
2
3
4
5
6
7
8
9
10
11
12
13

# 钩子

Pod hook(钩子)是由 Kubernetes 管理的 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为 Pod 中的所有容器都配置 hook。

Hook 的类型包括两种:

  • exec: 执行一段命令

  • HTTP: 发送 HTTP 请求

exec

apiVersion: v1
kind: Pod
metadata:
 name: lifecycle-exec-pod
spec:
 containers:
 - name: lifecycle-exec-container
   image: wangyanglinux/myapp:v1
   lifecycle:
     postStart:
       exec:
         command: ["/bin/sh", "-c", "echo postStart > /usr/share/message"]
     preStop:
       exec:
         command: ["/bin/sh", "-c", "echo preStop > /usr/share/message"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

基于 HTTP Get 方式

# 开启一个测试 webServer
$ docker run -it --rm -p 1234:80 wangyanglinux/myapp:v1.0
1
2
apiVersion: v1
kind: Pod
metadata:
 name: lifecycle-httpget-pod
 labels:
   name: lifecycle-httpget-pod
spec:
 containers:
 - name: lifecycle-httpget-container
   image: wangyanglinux/myapp:v1.0
   ports:
     - containerPort: 80
   lifecycle:
     postStart:
       httpGet:
         host: 66.235.170.12
         path: index.html
         port: 1234
     preStop:
       httpGet:
         host: 66.235.170.12
         path: hostname.html
         port: 1234
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: lifecycle-pod
 labels:
   app: lifecycle-pod
spec:
 containers:
 - name: busybox-container
   image: wangyanglinux/tools:busybox
   command: ["/bin/sh","-c","touch /tmp/live ; sleep 600; rm -rf /tmp/live; sleep3600"]
   livenessProbe:
     exec:
       command: ["test","-e","/tmp/live"]
     initialDelaySeconds: 1
     periodSeconds: 3
   lifecycle:
     postStart:
       httpGet:
         host: 66.235.170.12
         path: index.html
         port: 1234
     preStop:
       httpGet:
         host: 66.235.170.12
         path: hostname.html
         port: 1234
 - name: myapp-container
   image: wangyanglinux/myapp:v1.0
   livenessProbe:
     httpGet:
       port: 80
       path: /index.html
     initialDelaySeconds: 1
     periodSeconds: 3
     timeoutSeconds: 3
   readinessProbe:
     httpGet:
       port: 80
       path: /index1.html
     initialDelaySeconds: 1
     periodSeconds: 3
 initContainers:
 - name: init-myservice
   image: wangyanglinux/tools:busybox
   command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
 - name: init-mydb
   image: wangyanglinux/tools:busybox
   command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# pod控制器

在 Kubernetes 中运行了一系列控制器来确保集群的当前状态与期望状态保持一致,它们就是 Kubernetes 集群内部的管理控制中心或者说是"中心大脑"。例如,ReplicaSet 控制器负责维护集群中运行的 Pod 数量;Node 控制器负责监控节点的状态,并在节点出现故障时,执行自动化修复流程,确保集群始终处于预期的工作状态。

# ReplicationController

ReplicationController(RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收;

在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController。ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector;

  • 确保 Pod 副本数量始终符合用户定义
  • 自动替换异常退出的 Pod
  • 自动回收多余的 Pod(先回收创建时间较短的)

标签的匹配只要pod的标签包含控制器的所有标签即可(一般情况下)

apiVersion: v1
kind: ReplicationController
metadata:
 name: rc-demo
spec:
 replicas: 3
 selector:
   app: rc-demo
 template:
   metadata:
     labels:
       app: rc-demo
   spec:
     containers:
     - name: rc-demo-container
       image: wangyanglinux/myapp:v1.0
       env:
       - name: GET_HOSTS_FROM
         value: dns
         name: zhangsan
         value: "123"
       ports:
       - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# ReplicaSet

apiVersion: apps/v1
kind: ReplicaSet
metadata:
 name: rs-ml-demo
spec:
 replicas: 3
 selector:
   matchLabels:
     app: rs-ml-demo
 template:
   metadata:
     labels:
       app: rs-ml-demo
   spec:
     containers:
     - name: rs-ml-demo-container
       image: wangyanglinux/myapp:v1.0
       env:
       - name: GET_HOSTS_FROM
         value: dns
       ports:
       - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

selector.matchExpressions rs 在标签选择器上,除了可以定义键值对的选择形式,还支持 matchExpressions 字段,可以提供多种 选择。 目前支持的操作包括:

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在
apiVersion: apps/v1
kind: ReplicaSet
metadata:
 name: rs-me-exists-demo
spec:
 selector:
   matchExpressions:
     - key: app
       operator: Exists
 template:
   metadata:
     labels:
       app: spring-k8s
   spec:
     containers:
       - name: rs-me-exists-demo-container
         image: wangyanglinux/myapp:v1.0
         ports:
           - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: ReplicaSet
metadata:
 name: rs-me-in-demo
spec:
 selector:
   matchExpressions:
     - key: app
       operator: In
       values:
       - spring-k8s
       - hahahah
 template:
   metadata:
     labels:
       app: sg-k8s
   spec:
     containers:
       - name: rs-me-in-demo-container
         image: wangyanglinux/myapp:v1.0
         ports:
           - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Deployment

Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的 ReplicationController 来方便的管理应用。典型的应用场景包括:

  • 定义 Deployment 来创建 Pod 和 ReplicaSet
  • 滚动升级和回滚应用
  • 扩容和缩容
  • 暂停和继续 Deployment

声明性的东西是对终结果的陈述,表明意图而不是实现它的过程。在 Kubernetes 中,这就是说"应该有一个包含三个 Pod 的 ReplicaSet"。

命令式充当命令。声明式是被动的,而命令式是主动且直接的:"创建一个包含三个 Pod 的 ReplicaSet"。

# replace和apply 区别

kubectl replace: 使用新的配置完全替换掉现有资源的配置。这意味着新配置将覆盖现有资源的所有字段和属性,包括未指定的字段,会导致整个资源的替换 kubectl apply: 使用新的配置部分地更新现有资源的配置。它会根据提供的配置文件或参数(只会更新配置文件声明的部分,配置文件未声明的不会更新),只更新与新配置中不同的部分,而不会覆盖整个资源的配置字段级别的更新

kubectl replace: 由于是完全替换,所以会覆盖所有字段和属性,无论是否在新配置中指定 kubectl apply: 只更新与新配置中不同的字段和属性,保留未指定的字段不受影响

kubectl replace: 不支持部分更新,它会替换整个资源的配置 kubectl apply: 支持部分更新,只会更新新配置中发生变化的部分,保留未指定的部分不受影响与其他配置的影响

kubectl replace: 不考虑其他资源配置的状态,直接替换资源的配置 kubectl apply: 可以结合使用 -f 或 -k 参数,从文件目录中读取多个资源配置,并根据当前集群中的资源状态进行更新

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: myapp-deploy
 name: myapp-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: myapp-deploy
 template:
   metadata:
     labels:
       app: myapp-deploy
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: deployment-demo
 name: deployment-demo
spec:
 replicas: 5
 selector:
   matchLabels:
     app: deployment-demo
 template:
   metadata:
     labels:
       app: deployment-demo
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: deployment-demo-container
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 更新策略

Deployment 可以保证在升级时只有一定数量的 Pod 是 down 的。默认的,它会确保至少有比期望的Pod数量少一个是up状态(最多一个不可用)

Deployment 同时也可以确保只创建出超过期望数量的一定数量的 Pod。默认的,它会确保最多比期望的 Pod 数量多一个的 Pod 是 up 的(最多 1 个 surge )

kubectl explain deploy.spec.strategy.type
1
  • Recreate
  • rollingUpdate

​ maxSurge: 指定超出副本数有几个,两种方式:1、指定数量 2、百分比

​ maxUnavailable: 最多有几个不可用

金丝雀部署

kubectl apply -f 2.deployment.yaml
kubectl create svc clusterip  deployment-demo --tcp=80:80
kubectl patch deployment deployment-demo -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
# 这个时候会有11个pod 暂停滚动部署更新
kubectl patch deployment deployment-demo --patch '{"spec": {"template": {"spec": {"containers": [{"name": "deployment-demo-container","image":"wangyanglinux/myapp:v2.0"}]}}}}' && kubectl rollout pause deploy deployment-demo
# 恢复部署更新
kubectl rollout resume deploy deployment-demo
1
2
3
4
5
6
7

以上命令建议使用一下命令观察情况

 while true; do curl 10.105.187.100; done
1

回滚命令

# 查看滚动更新状态
kubectl rollout status deployment deployment-demo
echo $?  # 查看上一条命令的退出状态码
1
2
3
# 查看更新历史
kubectl rollout history deployment/deployment-demo
1
2
kubectl create -f deployment.yaml --record
1
# 回滚到指定版本
kubectl rollout undo deployment/deployment-demo --to-revision=2
1
2
# 暂停滚动更新
kubectl rollout pause deployment/deployment-demo
1
2

# DaemonSet

DaemonSet 确保全部(或者一些-除了master节点)Node 上运行一个 Pod 的副本。当有 Node 加入集群时也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

不会在master创建的原因是:master的污点(Taints)

kubectl describe node  node01
1
Taints:             node-role.kubernetes.io/control-plane:NoSchedule
                    # 或者
                    node-role.kubernetes.io/master:NoSchedule
1
2
3

使用 DaemonSet 的一些典型用法:

  • 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph
  • 在每个 Node 上运行日志收集 daemon,例如 fluentd、logstash
  • 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: deamonset-demo
  labels:
    app: daemonset-demo
spec:
  selector:
    matchLabels:
      name: deamonset-demo
  template:
    metadata:
      labels:
        name: deamonset-demo
    spec:
      containers:
      - name: daemonset-demo-container
        image: wangyanglinux/myapp:v1.0 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# job

Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束

特殊说明

  • spec.template 格式同 Pod
  • RestartPolicy 仅支持 Never 或 OnFailure
  • 单个 Pod 时,默认 Pod 成功运行后 Job 即结束
  • spec.completions 标志 Job 结束需要成功运行的 Pod 个数,默认为 1
  • spec.parallelism 标志并行运行的 Pod 的个数,默认为 1
  • spec.activeDeadlineSeconds 标志失败 Pod 的重试最大时间,超过这个时间不会继续重试
  • spec.backoffLimit 标志pod可以失败的次数,即同一个 Pod 模板失败超过 6 次(默认6次),Job 就会认为彻底失败,直接进入 Failed 状态,不再继续创建新的 Pod。
apiVersion: batch/v1
kind: Job
metadata:
 name: job-demo
spec:
 template:
   metadata:
     name: job-demo-pod
   spec:
     containers:
     - name: job-demo-container
       image: wangyanglinux/tools:maqingpythonv1
     restartPolicy: Never
1
2
3
4
5
6
7
8
9
10
11
12
13

控制为 1 的错误返回码

apiVersion: batch/v1
kind: Job
metadata:
 name: rand
spec:
 template:
   metadata:
     name: rand
   spec:
     containers:
     - name: rand
       image: wangyanglinux/tools:randexitv1
       args: ["--exitcode=1"]
     restartPolicy: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14

随机生成返回码

apiVersion: batch/v1
kind: Job
metadata:
  name: rand
spec:
  completions: 10
  parallelism: 5
  template:
    metadata:
      name: rand
    spec:
      containers:
        - name: rand
          image: wangyanglinux/tools:randexitv1
      restartPolicy: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# cronjob

Cron Job 管理基于时间的 Job,即: 在给定时间点只运行一次 周期性地在给定时间点运行

典型的用法如下所示: 在给定的时间点调度 Job 运行 创建周期性运行的 Job,例如:数据库备份、发送邮件

  • spec.schedule:调度,必需字段,指定任务运行周期,格式同 Cron
  • spec.jobTemplate:Job 模板,必需字段,指定需要运行的任务,格式同 Job
  • spec.startingDeadlineSeconds:启动 Job 的期限(秒级别),该字段是可选的。如果因为任何原因而错过了被调度的时间,那么错过执行时间的 Job 将被认为是失败的。如果没有指定,则没有期限
  • spec.concurrencyPolicy:并发策略,该字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种:

​ Allow(默认):允许并发运行 Job

​ Forbid:禁止并发运行,如果前一个还没有完成,则直接跳过下一个

​ Replace:取消当前正在运行的 Job,用一个新的来替换 ​ 注意,当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job,它们创建的 Job 之间总是允许并发运行。

  • spec.suspend :挂起,该字段也是可选的。如果设置为 true ,后续所有执行都会被挂起。它对已经开始执行的 Job 不起作用。默认值为 false

  • spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit :历史限制,是可选的字段。它们指定了可以保留多少完成和失败的 Job。默认情况下,它们分别设置为 3 和 1 。设置限制的值为 0 ,相关类型的 Job 完成后将不会被保留

apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-demo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      completions: 3
      template:
        spec:
          containers:
            - name: cronjob-demo-container
              image: busybox
              args:
                - /bin/sh
                - -c
                - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# Service

在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。 kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式

在 Kubernetes v1.0 版本,代理完全在 userspace。在 Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。从 Kubernetes v1.2 起,默认就是 iptables 代理。在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理.

更改为ipvs模式

每个节点操作

apt update -y
apt install ipvsadm ipset -y
1
2
cat <<EOF | tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF

# 立即加载
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

master 上执行

kubectl edit configmap kube-proxy -n kube-system
mode: "ipvs"

kubectl delete pod -n kube-system -l k8s-app=kube-proxy
kubectl get pods -n kube-system -l k8s-app=kube-proxy
1
2
3
4
5

service类型

  • ClusterIP:默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP,创建 Service 时不指定类型时的默认值,只能在 Kubernetes 集群内部访问。
  • NodePort:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 NodeIP:NodePort 来访问该服务,在每个节点上开放一个静态端口(30000-32767)
  • LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到 NodeIP:NodePort
  • ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持,通过 DNS CNAME 记录

# ClusterIP

apiVersion: apps/v1
kind: Deployment
metadata:
 name: myapp-clusterip-deploy
 namespace: default
spec:
 replicas: 3
 selector:
   matchLabels:
     app: myapp
     release: stabel
     svc: clusterip
 template:
   metadata:
     labels:
       app: myapp
       release: stabel
       env: test
       svc: clusterip
   spec:
     containers:
     - name: myapp-container
       image: wangyanglinux/myapp:v1.0
       imagePullPolicy: IfNotPresent
       ports:
       - name: http
         containerPort: 80
       readinessProbe:
         httpGet:
           port: 80
           path: /index1.html
         initialDelaySeconds: 1
         periodSeconds: 3
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
33
apiVersion: v1
kind: Service
metadata:
  name: myapp-clusterip
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
    svc: clusterip
  ports:
    - name: http
      port: 80
      targetPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

1758702603065.png

Cluster(默认)

流量会在 整个集群的所有 Pod 之间做负载均衡。

无论访问 Service 的 Pod 在哪个节点,流量都有可能被转发到任意一个符合 selector 的 Pod。

Local

流量只会转发到 和客户端在同一节点上的 Pod。

如果本节点没有对应的 Pod,那么请求会失败(没有 Endpoints)。

持久化链接

1758703186053.png

sessionAffinity: Clientip
1
root@node01:~/k8s/6# kubectl explain svc.spec.sessionAffinityConfig.clientIP
KIND:       Service
VERSION:    v1

FIELD: clientIP <ClientIPConfig>


DESCRIPTION:
    clientIP contains the configurations of Client IP based session affinity.
    ClientIPConfig represents the configurations of Client IP based session
    affinity.
    
FIELDS:
  timeoutSeconds        <integer>
    timeoutSeconds specifies the seconds of ClientIP type session sticky time.
    The value must be >0 && <=86400(for 1 day) if ServiceAffinity == "ClientIP".
    Default value is 10800(for 3 hours).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# NodePort

apiVersion: apps/v1
kind: Deployment
metadata:
 name: myapp-nodeport-deploy
 namespace: default
spec:
 replicas: 3
 selector:
   matchLabels:
     app: myapp
     release: stabel
     svc: nodeport
 template:
   metadata:
     labels:
       app: myapp
       release: stabel
       env: test
       svc: nodeport
   spec:
     containers:
     - name: myapp-container
       image: wangyanglinux/myapp:v1.0
       imagePullPolicy: IfNotPresent
       ports:
       - name: http
         containerPort: 80
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
apiVersion: v1
kind: Service
metadata:
 name: myapp-nodeport
 namespace: default
spec:
 type: NodePort
 selector:
   app: myapp
   release: stabel
   svc: nodeport
 ports:
 - name: http
   port: 80
   targetPort: 80
   nodePort: 30010
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

默认有负载均衡,可以通过任意一个node的真实IP:Port去访问,即使node上没有对应的pod运行

externalTrafficPolicy: Cluster #控制负载均衡
1

1758705681101.png

如果改为Local,则只能由对应运行的node去访问,并且只能访问其运行的pod

externalTrafficPolicy: Local
1

# LoadBalancer

参考链接 (opens new window)

apiVersion: v1
kind: Service
metadata:
    annotations:
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: ${YOUR_LB_ID}
        service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: 'true'
    labels:
        app: nginx
    name: my-nginx-svc
    namespace: default
spec:
    ports:
    - port: 80
      protocol: TCP
      targetPort: 80
    selector:
        app: nginx
    type: LoadBalancer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# ExternalName

kind: Service
apiVersion: v1
metadata:
    name: my-service-1
    namespace: default
spec:
    type: ExternalName
    externalName: www.baidu.com
1
2
3
4
5
6
7
8
# 在 Pod 内部访问
ping svcName.namespaceName.svc.cluster.local.
# 返回百度的IP
1
2
3

1758706571248.png

# Endpoints

1758780124218.png

自动关联体系:配置selector

手动关联体系:无配置selector

apiVersion: v1
kind: Service
metadata:
 name: nginx-noselectt
spec:
 ports:
   - protocol: TCP
     port: 6666
     targetPort: 80
---
apiVersion: v1
kind: Endpoints
metadata:
 name: nginx-noselectt
subsets:
 - addresses:
     - ip: 192.168.66.12
   ports:
     - port: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
docker run -itd -p 80:80 --net host wangyanglinux/myapp:v1
1

如果 Endpoint 需要跟踪多个 ip (多个 pod 或者容器或者应用),可以使用

  ' - ip: 172.17.0.2
     - ip: 172.17.0.3
     - ip: 172.17.0.4'
     ... ...
1
2
3
4

# publishNotReadyAddresses

在默认情况下,Kubernetes Service 只会将处于 Ready 状态的 Pod 的 IP 地址加入到其 Endpoints 列表(或现代 EndpointSlice 列表)中。客户端的请求只会被负载均衡到这些就绪的 Pod 上。

当设置了 publishNotReadyAddresses: true 后,Service 的行为会发生改变:允许 Kubernetes Service 将未就绪的 Pod 的 IP 地址发布到 Endpoints 中

创建pod

apiVersion: v1
kind: Pod
metadata:
 name: readiness-httpget-pod
 namespace: default
 labels:
   app: myapp
   env: test
spec:
 containers:
 - name: readiness-httpget-container
   image: wangyanglinux/myapp:v1.0
   imagePullPolicy: IfNotPresent
   readinessProbe:
     httpGet:
       port: 80
       path: /index1.html
     initialDelaySeconds: 1
     periodSeconds: 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

创建service

apiVersion: v1
kind: Service
metadata:
 labels:
   app: myapp
 name: myapp
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: myapp
 type: ClusterIP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

添加 publishNotReadyAddresses: true

kubectl patch service myapp -p '{"spec":{"publishNotReadyAddresses": true}}'
1

# 存储

元数据

  • configMap:用于保存配置数据(明文)

  • Secret:用于保存敏感性数据(编码)

  • Downward API:容器在运行时从 Kubernetes API 服务器获取有关它们自身的信息

真实数据

  • Volume:用于存储临时或者持久性数据

  • PersistentVolume:申请制的持久化存储

# configMap

ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制等对象

创建

# 从文件创建 ConfigMap
kubectl create configmap game-config --from-file=test.file
# 从字面值创建 ConfigMap
kubectl create configmap literal-config --from-literal=name=dave --from-literal=password=pass
1
2
3
4

# 环境变量

apiVersion: v1
kind: ConfigMap
metadata:
 name: literal-config
 namespace: default
data:
 name: dave
 password: pass
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: env-config
 namespace: default
data:
 log_level: INFO
---
apiVersion: v1
kind: Pod
metadata:
 name: cm-env-pod
spec:
 containers:
   - name: myapp-container
     image: wangyanglinux/myapp:v1.0
     command: [ "/bin/sh", "-c", "env" ]
     env:
       - name: USERNAME
         valueFrom:
           configMapKeyRef:
             name: literal-config
             key: name
       - name: PASSWORD
         valueFrom:
           configMapKeyRef:
             name: literal-config
             key: password
     envFrom:
       - configMapRef:
           name: env-config
 restartPolicy: Never
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
33
34
35
36
37
38
39
40
41

# 启动命令

apiVersion: v1
kind: Pod
metadata:
 name: cm-command-pod
spec:
 containers:
   - name: myapp-container
     image: wangyanglinux/myapp:v1.0
     command: [ "/bin/sh", "-c", "echo $(USERNAME) $(PASSWORD)" ]
     env:
       - name: USERNAME
         valueFrom:
           configMapKeyRef:
             name: literal-config
             key: name
       - name: PASSWORD
         valueFrom:
           configMapKeyRef:
             name: literal-config
             key: password
 restartPolicy: Never
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:
 name: cm-volume-pod
spec:
 containers:
   - name: myapp-container
     image: wangyanglinux/myapp:v1.0
     volumeMounts:
     - name: config-volume
       mountPath: /etc/config
 volumes:
   - name: config-volume
     configMap:
       name: literal-config
 restartPolicy: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 热更新

vim default.conf
1
server {
   listen 80 default_server;
   server_name example.com www.example.com;
   location / {
       root   /usr/share/nginx/html;
       index index.html index.htm;
    }
}
1
2
3
4
5
6
7
8
kubectl create cm default-nginx --from-file=default.conf
1
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: hotupdate-deploy
 name: hotupdate-deploy
spec:
 replicas: 5
 selector:
   matchLabels:
     app: hotupdate-deploy
 template:
   metadata:
     labels:
       app: hotupdate-deploy
   spec:
     containers:
     - image: nginx
       name: nginx
       volumeMounts:
       - name: config-volume
         mountPath: /etc/nginx/conf.d/
     volumes:
       - name: config-volume
         configMap:
           name: default-nginx
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

触发热更新

更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过修改 pod annotations 的方式强制触发滚动更新

kubectl patch deployment hotupdate-deploy --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config":"66666666"}}}}}'
1

更新 ConfigMap 后:

使用该 ConfigMap 挂载的 Env 不会同步更新 使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新


Kubernetes 给不可变的 ConfigMap 和 Secret 提供了一种可选配置,可以设置各个 Secret 和 ConfigMap 为不可变的。对于大量使用 configmap 的集群(至少有成千上万各不相同的 configmap 供 Pod 挂载),禁止变更它们的数据有下列好处:

主要优势: 防止意外(或非预期的)更新导致应用程序中断 通过将 configmap 标记为不可变来关闭 kube-apiserver 对其的监视,从而显著降低 kube-apiserver 的负载,提升集群性能。

KIND: ConfigMap  
VERSION: v1  

FIELD: immutable <boolean>  

DESCRIPTION:  
Immutable, if set to true, ensures that data stored in the ConfigMap cannot be updated (only object metadata can be modified). If not set to true, the field can be modified at any time. Defaulted to nil.
1
2
3
4
5
6
7

# Secret

Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。将这些信息放在 secret 中比放在 Pod 的定义或者容器镜像中来说更加安全和灵活。

  • Kubernetes 通过仅仅将 Secret 分发到需要访问 Secret 的 Pod 所在的机器节点来保障其安全性

  • Secret 只会存储在节点的内存中,永不写入物理存储,这样从节点删除 Secret 时就不需要擦除磁盘数据

  • 从 Kubernetes 1.7 版本开始,etcd 会以加密形式存储 Secret,一定程度的保证了 Secret 安全性

类型

  • 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 → 启动引导令牌数据

# Opaque

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

1758787723177.png

Opaque Secret env

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: opaque-secret-env
 name: opaque-secret-env-deploy
spec:
 replicas: 5
 selector:
   matchLabels:
     app: op-se-env-pod
 template:
   metadata:
     labels:
       app: op-se-env-pod
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp-continaer
       ports:
       - containerPort: 80
       env:
       - name: TEST_USER
         valueFrom:
           secretKeyRef:
             name: mysecret
             key: username
       - name: TEST_PASSWORD
         valueFrom:
           secretKeyRef:
             name: mysecret
             key: password
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

1758788045668.png

Opaque Secret Volume

apiVersion: v1
kind: Pod
metadata:
 labels:
   name: secret-volume
 name: secret-volume-pod
spec:
 volumes:
 - name: volumes12
   secret:
     secretName: mysecret
 containers:
 - image: wangyanglinux/myapp:v1.0
   name: myapp-container
   volumeMounts:
   - name: volumes12
     mountPath: "/data"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 设置保存文件的权限
 volumes:
 - name: volumes12
   secret:
     secretName: mysecret
     defaultMode: 256
# 设置要保存挂载的选项,这里只保存username      
 volumes:
 - name: volumes12
   secret:
     secretName: mysecret
     items:
     - key: username
       path: my-group/my-username
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# downward-api

Downward API 是 Kubernetes 中的一个功能,它允许容器在运行时从 Kubernetes API 服务器获取有关它们自身的信息。这些信息可以作为容器内部的环境变量或文件注入到容器中,以便容器可以获取有关其运行环境的各种信息,如 Pod 名称、命名空间、标签等

  • 提供容器元数据

  • 动态配置

  • 与 Kubernetes 环境集成

env

apiVersion: v1
kind: Pod
metadata:
 name: downward-api-env-example
spec:
 containers:
 - name: my-container
   image: wangyanglinux/myapp:v1.0
   env:
   - name: POD_NAME
     valueFrom:
       fieldRef:
         fieldPath: metadata.name
   - name: POD_NAMESPACE
     valueFrom:
       fieldRef:
         fieldPath: metadata.namespace
   - name: POD_IP
     valueFrom:
       fieldRef:
         fieldPath: status.podIP
   - name: CPU_REQUEST
     valueFrom:
       resourceFieldRef:
         resource: requests.cpu
   - name: CPU_LIMIT
     valueFrom:
       resourceFieldRef:
         resource: limits.cpu
   - name: MEMORY_REQUEST
     valueFrom:
       resourceFieldRef:
         resource: requests.memory
   - name: MEMORY_LIMIT
     valueFrom:
       resourceFieldRef:
         resource: limits.memory
 restartPolicy: Never
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
33
34
35
36
37
38

volume

apiVersion: v1
kind: Pod
metadata:
 name: downward-api-volume-example
spec:
 containers:
 - name: my-container
   image: wangyanglinux/myapp:v1.0
   resources:
     limits:
       cpu: "1"
       memory: "512Mi"
     requests:
       cpu: "0.5"
       memory: "256Mi"
   volumeMounts:
   - name: downward-api-volume
     mountPath: /etc/podinfo
 volumes:
 - name: downward-api-volume
   downwardAPI:
     items:
     - path: "annotations"
       fieldRef:
         fieldPath: metadata.annotations
     - path: "labels"
       fieldRef:
         fieldPath: metadata.labels
     - path: "name"
       fieldRef:
         fieldPath: metadata.name
     - path: "namespace"
       fieldRef:
         fieldPath: metadata.namespace
     - path: "uid"
       fieldRef:
         fieldPath: metadata.uid
     - path: "cpuRequest"
       resourceFieldRef:
         containerName: my-container
         resource: requests.cpu
     - path: "memoryRequest"
       resourceFieldRef:
         containerName: my-container
         resource: requests.memory
     - path: "cpuLimit"
       resourceFieldRef:
         containerName: my-container
         resource: limits.cpu
     - path: "memoryLimit"
       resourceFieldRef:
         containerName: my-container
         resource: limits.memory
 restartPolicy: Never
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

基于 apiServer 访问集群

Downward API 提供了一种简单的方式,将 pod 和容器的元数据传递给在它们内部运行的进程。但这种方式其实仅仅可以暴露一个 pod 自身的元数据,而且只可以暴露部分元数据。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
 name: test-api-cluster-admin-binding
subjects:
- kind: ServiceAccount
  name: test-api
  namespace: default
roleRef:
 kind: ClusterRole
 name: cluster-admin
 apiGroup: rbac.authorization.k8s.io
1
2
3
4
5
6
7
8
9
10
11
12
kubectl create sa test-api
1
apiVersion: v1
kind: Pod
metadata:
 name: curl
spec:
 serviceAccountName: test-api
 containers:
 - name: main
   image: curlimages/curl:latest
   command: ["sleep", "9999"]
1
2
3
4
5
6
7
8
9
10
kubectl exec -it curl -- /bin/bash
root@curl:/# TOKEN=$( cat /var/run/secrets/kubernetes.io/serviceaccount/token )
root@curl:/# CAPATH="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
root@curl:/# NS=$( cat /var/run/secrets/kubernetes.io/serviceaccount/namespace )
root@curl:/# curl -H "Authorization: Bearer $TOKEN" --cacert $CAPATH https://kubernetes/api/v1/namespaces/$NS/pods
1
2
3
4
5
kubectl proxy —port=8080
curl localhost:8080/openapi/v2 > k8s-swagger.json
docker run --rm -d -p 80:8080 -e SWAGGER_JSON=/k8s-swagger.json -v $(pwd)/k8s-swagger.json:/k8s-swagger.json swaggerapi/swagger-ui
1
2
3

# Volume

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在 Pod中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的 Volume抽象就很好的解决了这些问题

类型:

awsElasticBlockStore 、azureDisk、azureFile、cephfs、 csidownwardAPI、 emptyDir、fc

flocker、gcePersistentDisk、gitRepo、glusterfs、hostPath、iscsi

local、nfs、persistentVolumeClaim、projected、portworxVolume

quobyte、rbd、scaleIO、secret、storageos、vsphereVolume

# emptydir-disk

当Pod被分配给节点时,首先创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除Pod时,emptyDir中的数据将被永久删除。

容器崩溃不会从节点中移除pod,因此emptyDir卷中的数据在容器崩溃时是安全的。

emptyDir的用法有:

  • 暂存空间,例如用于基于磁盘的合并排序、用作长时间计算崩溃恢复时的检查点
  • Web服务器容器提供数据时,保存内容管理器容器提取的文件

在kubelet的工作目录(root-dir参数控制),默认为/var/lib/kubelet,会为每个使用了emptyDir:{}的pod创建一个目录,格式如**/var/lib/kubelet/pods/{poduid}/volumes/kubernetes.io~empty-dir/,所有放在emptyDir中数据,最终都是落在了node的上述路径中。(在运行pod的node上)**

apiVersion: v1
kind: Pod
metadata:
 name: volume-emptydir-disk-pod
 namespace: default
spec:
 containers:
 - name: myapp
   image: wangyanglinux/myapp:v1.0
   ports:
   - containerPort: 80
   volumeMounts:
   - name: logs-volume
     mountPath: /usr/local/nginx/logs
 - name: busybox
   image: wangyanglinux/tools:busybox
   command: ["/bin/sh","-c","touch /logs/access.log && tail -f /logs/access.log"]
   volumeMounts:
   - name: logs-volume
     mountPath: /logs
 volumes:
 - name: logs-volume
   emptyDir: {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
kubectl get pod volume-emptydir-disk-pod -o yaml | grep uid
1

1758802187862.png

# emptydir-mem

apiVersion: v1
kind: Pod
metadata:
 name: volume-emptydir-mem
 namespace: default
spec:
 containers:
 - name: myapp
   image: wangyanglinux/myapp:v1.0
   ports:
   - containerPort: 80
   resources:
     limits:
       cpu: "1"
       memory: 1024Mi
     requests:
       cpu: "1"
       memory: 1024Mi
   volumeMounts:
   - name: mem-volume
     mountPath: /data
 volumes:
 - name: mem-volume
   emptyDir:
     medium: Memory
     sizeLimit: 500Mi
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

# hostPath

hostPath 卷将主机节点的文件系统中的文件或目录挂载到集群中

hostPath 用途如下

  • 运行需要访问 Docker 内部的容器;使用 /var/lib/docker 的 hostPath

  • 在容器中运行 cAdvisor;使用 /dev/cgroups 的 hostPath

  • 允许 pod 指定给定的 hostPath 是否应该在 pod 运行之前存在,是否应该创建,以及它应该以什么形式存在

除了所需的 path 属性之外,用户还可以为 hostPath 卷指定 type

注意:

  • 由于每个节点上的文件都不同,具有相同配置(例如从 podTemplate 创建的)的 pod 在不同节点上的行为可能会有所不同
  • 当 Kubernetes 按照计划添加资源感知调度时,将无法考虑 hostPath使用的资源
  • 在底层主机上创建的文件或目录只能由 root 写入。您需要在特权容器中以 root 身份运行进程,或修改主机上的文件权限以便写入 hostPath卷

参数

  • 空:(默认) 空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查。
  • DirectoryOrCreate: 如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。
  • Directory: 给定的路径下必须存在目录
  • FileOrCreate: 如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。
  • File: 给定的路径下必须存在文件
  • Socket: 给定的路径下必须存在 UNIX 套接字
  • CharDevice: 给定的路径下必须存在字符设备
  • BlockDevice: 给定的路径下必须存在块设备
apiVersion: v1
kind: Pod
metadata:
 name: hostpath-pod
spec:
 containers:
 - image: wangyanglinux/myapp:v1.0
   name: myapp
   volumeMounts:
   - mountPath: /test-pd
     name: test-volume
 volumes:
 - name: test-volume
   hostPath:
      # directory location on host
     path: /data
      # this field is optional
     type: Directory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# PV/PVC

pv/pvc关联方式

  • 容量:PV的值不小于PVC要求,可以大于最好一致

  • 读写策略:完全匹配

  • 单节点读写-ReadWriteOnce-RWO

  • 多节点只读-ReadOnlyMany-ROX

  • 多节点读写-ReadWriteMany-RWX

  • 存储类:PV的类与PVC的类必须一致,不存在包容降级关系

pv/pvc回收策略

  • Retain(保留):手动回收
  • Recycle(回收):基本擦除(rm -rf /thevolume/*)
  • Delete(删除):关联的存储资产(例如AWS EBS、GCE PD、Azure Disk 和OpenStack Cinder 卷)将被删除
  • 当前,只有NFS和HostPath支持回收策略。AWS EBS、GCE PD、Azure Disk和Cinder卷支持删除策略

pv/pvc状态

  • Available(可用)- 一块空闲资源还没有被任何声明所绑定

  • Bound(已绑定)- 卷已经被声明绑定

  • Released(已释放)- 声明被删除,但是资源还未被集群重新声明

  • Failed(失败)- 该卷的自动回收失败

  • 命令行会显示绑定到PV的PVC的名称

pv/pvc-pvc保护

PVC 保护的目的是确保由 pod 正在使用的 PVC 不会从系统中移除,因为如果被移除的话可能会导致数据丢失。 注意:当 pod 状态为 Pending并且 pod 已经分配给节点或 pod 为 Running状态时,PVC 处于活动状态 当启用 PVC 保护功能时,如果用户删除了一个 pod 正在使用的 PVC,则该 PVC 不会被立即删除。PVC 的删除将被推迟,直到 PVC 不再被任何 pod 使用。

# StatefulSet部署

特性

  • 稳定的网络访问模式
  • 稳定的存储卷
  • 有序创建,有序删除

# 安装nfs

客户端

apt update
apt install nfs-common -y
1
2

服务端

apt update
apt install nfs-kernel-server -y
1
2

服务端执行

mkdir /nfsdata
chmod 666 /nfsdata
chown nobody /nfsdata
cat /etc/exports
 /nfsdata/1 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/2 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/3 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/4 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/5 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/6 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/7 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/8 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/9 *(rw,no_root_squash,no_all_squash,sync)
 /nfsdata/10 *(rw,no_root_squash,no_all_squash,sync)
cd /nfsdata
mkdir {1..10}
echo 1 >> 1/index.html
echo 2 >> 2/index.html
echo 3 >> 3/index.html
echo 4 >> 4/index.html
echo 5 >> 5/index.html
echo 6 >> 6/index.html
echo 7 >> 7/index.html
echo 8 >> 8/index.html
echo 9 >> 9/index.html
echo 10 >> 10/index.html
systemctl restart nfs-server
# 查看共享结果
showmount -e ServerIP
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

客户端

mkdir /nfstest
mount -t nfs ServerIP:/nfsdata/1 /nfstest/
# 解除挂载
umount /nfstest/
1
2
3
4

部署 PV

apiVersion: v1
kind: PersistentVolume
metadata:
 name: nfspv1
spec:
 capacity:
   storage: 1Gi
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Recycle
 storageClassName: nfs
 nfs:
   path: /nfsdata/1
   server: 66.235.170.12
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: nfspv2
spec:
 capacity:
   storage: 0.9Gi
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Recycle
 storageClassName: nfs
 nfs:
   path: /nfsdata/2
   server: 66.235.170.12
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: nfspv3
spec:
 capacity:
   storage: 1.2Gi
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Recycle
 storageClassName: nfs
 nfs:
   path: /nfsdata/3
   server: 66.235.170.12
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: nfspv4
spec:
 capacity:
   storage: 1Gi
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Recycle
 storageClassName: nfs
 nfs:
   path: /nfsdata/4
   server: 66.235.170.12
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: nfspv5
spec:
 capacity:
   storage: 1Gi
 accessModes:
   - ReadWriteMany
 persistentVolumeReclaimPolicy: Recycle
 storageClassName: nfs
 nfs:
   path: /nfsdata/5
   server: 66.235.170.12
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: nfspv6
spec:
 capacity:
   storage: 1Gi
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Recycle
 storageClassName: nfs1
 nfs:
   path: /nfsdata/6
   server: 66.235.170.12
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: nfspv7
spec:
 capacity:
   storage: 1Gi
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Retain
 storageClassName: nfs
 nfs:
   path: /nfsdata/7
   server: 66.235.170.12
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

创建服务并使用 PVC

apiVersion: v1
kind: Service
metadata:
 name: nginx
 labels:
   app: nginx
spec:
 ports:
 - port: 80
   name: web
 clusterIP: None
 selector:
   app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: web
spec:
 selector:
   matchLabels:
     app: nginx
 serviceName: "nginx"
 replicas: 3
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: wangyanglinux/myapp:v1.0
       ports:
       - containerPort: 80
         name: web
       volumeMounts:
       - name: www
         mountPath: /usr/local/nginx/html
 volumeClaimTemplates:
 - metadata:
     name: www
   spec:
     accessModes: [ "ReadWriteOnce" ]
     storageClassName: "nfs"
     resources:
       requests:
         storage: 1Gi
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# storageclass

StorageClass 是一种资源对象,用于定义持久卷(Persistent Volumes)的动态供给(Dynamic Provisioning)策略。StorageClass 允许管理员定义不同类型的存储,并指定如何动态创建持久卷以供应用程序使用。这使得 Kubernetes 集群中的存储管理更加灵活和自动化。

vim /etc/exports
# 新增
/nfsdata/share *(rw,no_root_squash,no_all_squash,sync)
mkdir /nfsdata/share
chown -R nobody /nfsdata/share/
systemctl restart nfs-server
1
2
3
4
5
6

部署 nfs-client-provisioner

nfs-client-provisioner 是一个 Kubernetes 供应商,用于动态提供由 NFS (Network File System) 共享支持的持久卷。在 Kubernetes 中,持久卷是独立于 pod 存在的存储资源,可以在 pod 重新启动或重新调度时持久地存储数据。 nfs-client-provisioner 自动化了根据需要创建持久卷的过程,通过与 NFS 服务器交互。在需要在 Kubernetes 集群中为应用程序动态分配存储而无需手动管理 NFS 共享和持久卷创建的情况下,这尤其有用。

kind: Deployment
apiVersion: apps/v1
metadata:
 name: nfs-client-provisioner
 namespace: nfs-storageclass
spec:
 replicas: 1
 selector:
   matchLabels:
     app: nfs-client-provisioner
 strategy:
   type: Recreate
 template:
   metadata:
     labels:
       app: nfs-client-provisioner
   spec:
     serviceAccountName: nfs-client-provisioner
     containers:
       - name: nfs-client-provisioner
          # image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
         image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
         volumeMounts:
           - name: nfs-client-root
             mountPath: /persistentvolumes
         env:
           - name: PROVISIONER_NAME
             value: k8s-sigs.io/nfs-subdir-external-provisioner
           - name: NFS_SERVER
              # value: <YOUR NFS SERVER HOSTNAME>
             value: 66.235.170.12
           - name: NFS_PATH
              # value: /var/nfs
             value: /nfsdata/share
     volumes:
       - name: nfs-client-root
         nfs:
            # server: <YOUR NFS SERVER HOSTNAME>
           server: 66.235.170.12
            # share nfs path
           path: /nfsdata/share
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
33
34
35
36
37
38
39
40
41
apiVersion: v1
kind: ServiceAccount
metadata:
 name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
 namespace: nfs-storageclass
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: nfs-client-provisioner-runner
rules:
 - apiGroups: [""]
   resources: ["nodes"]
   verbs: ["get", "list", "watch"]
 - apiGroups: [""]
   resources: ["persistentvolumes"]
   verbs: ["get", "list", "watch", "create", "delete"]
 - apiGroups: [""]
   resources: ["persistentvolumeclaims"]
   verbs: ["get", "list", "watch", "update"]
 - apiGroups: ["storage.k8s.io"]
   resources: ["storageclasses"]
   verbs: ["get", "list", "watch"]
 - apiGroups: [""]
   resources: ["events"]
   verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: run-nfs-client-provisioner
subjects:
 - kind: ServiceAccount
   name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
   namespace: nfs-storageclass
roleRef:
 kind: ClusterRole
 name: nfs-client-provisioner-runner
 apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
 namespace: nfs-storageclass
rules:
 - apiGroups: [""]
   resources: ["endpoints"]
   verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
 namespace: nfs-storageclass
subjects:
 - kind: ServiceAccount
   name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
   namespace: nfs-storageclass
roleRef:
 kind: Role
 name: leader-locking-nfs-client-provisioner
 apiGroup: rbac.authorization.k8s.io
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
 name: nfs-client
 namespace: nfs-storageclass
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
 pathPattern: ${.PVC.namespace}/${.PVC.name}
 onDelete: delete
1
2
3
4
5
6
7
8
9

创建名字空间

kubectl create ns nfs-storageclass
1

创建测试pod

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
 name: test-claim
 annotations: 
spec:
 accessModes:
   - ReadWriteMany
 resources:
   requests:
     storage: 1Mi
 storageClassName: nfs-client
---
kind: Pod
apiVersion: v1
metadata:
 name: test-pod
spec:
 containers:
 - name: test-pod
   image: wangyanglinux/myapp:v1.0
   volumeMounts:
     - name: nfs-pvc
       mountPath: "/usr/local/nginx/html"
 restartPolicy: "Never"
 volumes:
   - name: nfs-pvc
     persistentVolumeClaim:
       claimName: test-claim
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

# 调度器

Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上

Scheduler 是作为单独的程序运行的,启动之后会一直监听 API Server,获取 PodSpec.NodeName 为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上。

概念听起来是非常简单的,但有很多要考虑的问题:

◆ 公平:如何保证每个节点都能被分配资源

◆ 资源高效利用:集群所有资源最大化被使用

◆ 效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作

◆ 灵活:允许用户根据自己的需求控制调度的逻辑

调度过程

调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为预选;然后对通过的节点按照优先级排序,这个是优选;最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误

预选

  • PodFitsResources: 节点上剩余的资源是否大于 pod 请求的资源
  • PodFitsHost: 如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配
  • PodFitsHostPorts: 节点上已经使用的 port 是否和 pod 申请的 port 冲突
  • PodSelectorMatches: 过滤掉和 pod 指定的 label 不匹配的节点
  • NoDiskConflict: 已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读

优选

如果在预选过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续优选过程:按照优先级大小对节点排序。 优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括:

  • LeastRequestedPriority:通过计算 CPU 和 Memory 的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点。
  • BalancedResourceAllocation:节点上 CPU 和 Memory 使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用。
  • ImageLocalityPriority:倾向于已经有所需镜像的节点,镜像总大小值越大,权重越高。

# 亲和性(Affinity)

node亲和性

preferredDuringSchedulingIgnoredDuringExecution:软亲和

apiVersion: v1
kind: Pod
metadata:
 name: node-affinity-preferred
 labels:
   app: node-affinity-preferred
spec:
 containers:
 - name: node-affinity-preferred-pod
   image: wangyanglinux/myapp:v1.0
 affinity:
   nodeAffinity:
     preferredDuringSchedulingIgnoredDuringExecution:
     - weight: 1
       preference:
         matchExpressions:
         - key: domain
           operator: In
           values:
           - blog
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

requiredDuringSchedulingIgnoredDuringExecution:硬亲和

apiVersion: v1
kind: Pod
metadata:
 name: node-affinity-required
 labels:
   app: node-affinity-required
spec:
 containers:
 - name: node-affinity-required-pod
   image: wangyanglinux/myapp:v1.0
 affinity:
   nodeAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
       nodeSelectorTerms:
       - matchExpressions:
         - key: kubernetes.io/hostname
           operator: In
           values:
           - node06
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

pod亲和性

preferredDuringSchedulingIgnoredDuringExecution:软亲和**

apiVersion: v1
kind: Pod
metadata:
 name: pod-aff-prefer
 labels:
   app: pod-aff
spec:
 containers:
 - name: myapp
   image: wangyanglinux/myapp:v1.0
 affinity:
   podAffinity:
     preferredDuringSchedulingIgnoredDuringExecution:
     - weight: 1
       podAffinityTerm:
         labelSelector:
           matchExpressions:
           - key: app
             operator: In
             values:
             - pod-1
         topologyKey: kubernetes.io/hostname
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

requiredDuringSchedulingIgnoredDuringExecution:硬亲和

apiVersion: v1
kind: Pod
metadata:
 name: pod-aff-req
 labels:
   app: pod-aff-req
spec:
 containers:
 - name: pod-aff-req-c
   image: wangyanglinux/myapp:v1.0
 affinity:
   podAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
     - labelSelector:
         matchExpressions:
         - key: app
           operator: In
           values:
           - pod-1
       topologyKey: kubernetes.io/hostname
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 反亲和性

preferredDuringSchedulingIgnoredDuringExecution:软反亲和**

apiVersion: v1
kind: Pod
metadata:
 name: pod-antiaff-prefer
 labels:
   app: pod-aff
spec:
 containers:
 - name: myapp
   image: wangyanglinux/myapp:v1.0
 affinity:
   podAntiAffinity:
     preferredDuringSchedulingIgnoredDuringExecution:
     - weight: 1
       podAffinityTerm:
         labelSelector:
           matchExpressions:
           - key: app
             operator: In
             values:
             - pod-2
         topologyKey: kubernetes.io/hostname
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

requiredDuringSchedulingIgnoredDuringExecution:硬反亲和

apiVersion: v1
kind: Pod
metadata:
 name: pod-antiaff-prefer
 labels:
   app: pod-aff
spec:
 containers:
 - name: myapp
   image: wangyanglinux/myapp:v1.0
 affinity:
   podAntiAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
     - weight: 1
       podAffinityTerm:
         labelSelector:
           matchExpressions:
           - key: app
             operator: In
             values:
             - pod-2
         topologyKey: kubernetes.io/hostname
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

自定义调度器

除了 kubernetes 自带的调度器,你也可以编写自己的调度器。通过 spec:schedulername参数指定调度器的名字,可以为 pod 选择某个调度器进行调度。比如下面的 pod 选择 my-scheduler进行调度,而不是默认的 default-scheduler:

# 在 kubernetes Master 节点开启 apiServer 的代理
$ kubectl proxy --port=8001
1
2

基于 shell 编写一个自定义调度器

# vi my-scheduler.sh
#!/bin/bash
SERVER='localhost:8001'
while true;
do
    for PODNAME in $(kubectl --server $SERVER get pods -o json | jq '.items[] | 
select(.spec.schedulerName =="my-scheduler") | select(.spec.nodeName == null) | 
.metadata.name' | tr -d '"')
    do
        NODES=($(kubectl --server $SERVER get nodes -o json | jq 
'.items[].metadata.name' | tr -d '"'))
        NUMNODES=${#NODES[@]}
        CHOSEN=${NODES[$[ $RANDOM % $NUMNODES]]}
        curl --header "Content-Type:application/json" --request POST --data
'{"apiVersion":"v1","kind":"Binding","metadata": {"name":"'$PODNAME'"},"target": 
{"apiVersion":"v1","kind": "Node", "name": "'$CHOSEN'"}}'
http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/
        echo "Assigned $PODNAME to $CHOSEN"
    done
    sleep 1
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

创建一个 deployment 尝试

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: myapp
 name: myapp
spec:
 replicas: 1
 selector:
   matchLabels:
     app: myapp
 template:
   metadata:
     labels:
       app: myapp
   spec:
     schedulerName: my-scheduler
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 污点容忍

Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有匹配 taint 的节点上。

污点

key=value:effect 每个污点有一个 key 和 value 作为污点的标签,其中 value 可以为空,effect 描述污点的作用。当前 taint effect 支持如下三个选项: NoSchedule:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上 PreferNoSchedule:表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上 NoExecute:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐出去

# 设置污点
kubectl taint nodes node1 key1=value1:NoSchedule

# 节点说明中,查找 Taints 字段
kubectl describe pod pod-name

# 去除污点
kubectl taint nodes node1 key1:NoSchedule-
1
2
3
4
5
6
7
8

容忍

设置了污点的Node将根据taint的effect:NoSchedule、PreferNoSchedule、NoExecute和Pod之间产生互斥的关系,Pod将在一定程度上不会被调度到Node上。但我们可以在Pod上设置容忍(Toleration),意思是设置了容忍的Pod将可以容忍污点的存在,可以被调度到存在污点的Node上。

设置方式

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
1
2
3
4
5
tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600
1
2
3
4
5
6

特殊类型

当不指定 value时,表示容忍所有的污点 value

tolerations:
- key: "key2"
  operator: "Exists"
  effect: "NoSchedule"
1
2
3
4

当不指定 key值时,表示容忍所有的污点 key

tolerations:
- operator: "Exists"
1
2

当不指定 effect 值时,表示容忍所有的污点作用

tolerations:
- key: "key"
  operator: "Exists"
1
2
3

有多个 Master 存在时,防止资源浪费

kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule
1

# 固定节点调度

指定节点调度(pod.spec.nodeName)

忽略污点设置

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nodename-test
spec:
 replicas: 7
 selector:
   matchLabels:
     app: nodename
 template:
   metadata:
     labels:
       app: nodename
   spec:
     nodeName: k8s-node01
     containers:
     - name: myweb
       image: wangyanglinux/myapp:v1.0
       ports:
       - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

指点节点标签调度(pod.spec.nodeSelector)

任然受污点的影响

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nodeselect-test
spec:
 replicas: 2
 selector:
   matchLabels:
     app: nodeselect
 template:
   metadata:
     labels:
       app: nodeselect
   spec:
     nodeSelector:
       type: nodeselect
     containers:
     - name: myweb
       image: wangyanglinux/myapp:v1.0
       ports:
       - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# HELM

Helm 是 Kubernetes 的包管理工具,类似于 Linux 世界里的 apt 或 yum。 它把一组 Kubernetes 资源(YAML 文件)打包成一个 Chart,方便安装、升级、回滚和管理。

Helm 是官方提供的类似于 YUM 的包管理器,是部署环境的流程封装。Helm 有两个重要的概念:chart 和 release

  • Chart:是创建一个应用的信息集合,包括各种 Kubernetes 对象的配置模板、参数定义、依赖关系、文档说明等。chart 是应用部署的自包含逻辑单元。可以将 chart 想象成 apt、yum 中的软件安装包
  • Release:是 chart 的运行实例,代表了一个正在运行的应用。当 chart 被安装到 Kubernetes 集群,就生成一个 release。chart 能够多次安装到同一个集群,每次安装都是一个 release
  • Helm cli:helm 客户端组件,负责和 kubernetes apiS 通信
  • Repository:用于发布和存储 Chart 的仓库

# 安装

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
helm version
1
2
3
4

初始化

当您已经安装好了Helm之后,您可以添加一个chart 仓库。从 Artifact Hub (opens new window) 中查找有效的Helm chart仓库

helm repo add bitnami https://charts.bitnami.com/bitnami
1

当添加完成,您将可以看到可以被您安装的 charts 列表:

helm search repo bitnami
1

安装 chart 示例

helm repo update  # 确定我们可以拿到最新的 charts 列表
helm show values bitnami/apache  # 显示可配置参数,预览默认值
helm install bitnami/apache --generate-name # 自动生成名字
helm install apache-1612624192 bitnami/apache # 指定名字
helm ls
helm show chart bitnami/apache # chart 的基本信息
helm show all bitnami/apache # chart 的所有信息
1
2
3
4
5
6
7

安装资源顺序

Namespace > NetworkPolicy > ResourceQuota > LimitRange > PodSecurityPolicy > PodDisruptionBudget > ServiceAccount > Secret > SecretList > ConfigMap > StorageClass
PersistentVolume > PersistentVolumeClaim > CustomResourceDefinition 
> ClusterRole
ClusterRoleList > ClusterRoleBinding > ClusterRoleBindingList > Role 
> RoleList
RoleBinding > RoleBindingList > Service > DaemonSet > Pod > 
ReplicationController > ReplicaSet > Deployment > 
HorizontalPodAutoscaler > StatefulSet > Job > CronJob > Ingress > 
APIService
1
2
3
4
5
6
7
8
9

卸载一个版本

helm uninstall apache-1758962180 # 该命令会从Kubernetes卸载 apache-1758962180,它将删除和该版本相关的所有相关资源(service、deployment、 pod等等)甚至版本历史
 --keep-history # 选项, Helm 将会保存版本历史
 
helm status apache-1612624192 # 查看该版本的信息
1
2
3
4
# 用于在 Helm Hub(https://hub.helm.sh)上搜索 Helm charts
helm search hub wordpress
# 用于在配置的 Helm 仓库中搜索 Helm charts,~/.config/helm/repositories.yaml 中被定义持久化
helm search repo wordpress
# Helm 搜索使用模糊字符串匹配算法,所以你可以只输入名字的一部分
1
2
3
4
5

安装前自定义 chart

helm show values bitnami/apache # 查看 chart 中的可配置选项
# 使用 YAML 格式的文件覆盖上述任意配置项,并在安装过程中使用该文件
vi values.yaml
service:
 type: NodePort
  
helm install -f values.yaml bitnami/apache --generate-name
1
2
3
4
5
6
7

安装过程中有两种方式传递配置数据

--values (或 -f ):使用 YAML 文件覆盖配置。可以指定多次,优先使用最右边的文件

--set :通过命令行的方式对指定项进行覆盖

如果同时使用两种方式,则 --set 中的值会被合并到 --values 中,但是 --set 中的值优先级更高。
在 --set 中覆盖的内容会被被保存在 ConfigMap 中。可以通过 helm get values <release-name> 来
查看指定 release 中 --set 设置的值。也可以通过运行 helm upgrade 并指定 --reset-values 字段来
清除 --set 中设置的值
1
2
3
4
5
6
7
8

更多安装方法

  • helm install 命令可以从多个来源进行安装:
  • chart 的仓库(如上所述)
  • 本地 chart 压缩包( helm install foo foo-0.1.1.tgz )
  • 解压后的 chart 目录( helm install foo path/to/foo )
  • 完整的 URL( helm install foo https://example.com/charts/foo-1.2.3.tgz )

'helm upgrade' 和 'helm rollback':升级 release 和失败时恢复 当你想升级到 chart 的新版本,或是修改 release 的配置,你可以使用 helm upgrade 命令。Helm 会 尝试执行最小侵入式升级。即它只会更新自上次发布以来发生了更改的内容

helm upgrade -f clusterip.yaml apache-1758962840 bitnami/apache
1

在上面的例子中, apache-1758962840 这个 release 使用相同的 chart 进行升级,但是使用了一个新的YAML 文件:

service:
 type: ClusterIP
1
2

我们可以使用 helm get values 命令来看看配置值是否真的生效了

helm get values apache-1758962840
1

现在,假如在一次发布过程中,发生了不符合预期的事情,也很容易通过 helm rollback [RELEASE] [REVISION] 命令回滚到之前的发布版本

helm rollback apache-1758962840 1
1

上面这条命令将我们的 apache-1758962840 回滚到了它最初的版本。release 版本其实是一个增量修订(revision)。 每当发生了一次安装、升级或回滚操作,revision 的值就会加1。第一次 revision 的值永远是1。我们可以使用 helm history [RELEASE] 命令来查看一个特定 release 的修订版本号

helm history apache-1758962840
1

创建一个自己的 Chart

# 1、创建一个模板
helm create myapp
# 2、删除不用的文件
rm -rf templates/* values.yaml 
# 3、编写 template 下的 service 和 deployment 资源清单
1
2
3
4
5
vim templates/nodePort.yaml
1
apiVersion: v1
kind: Service
metadata:
 labels:
  app: myapp-test
 name: myapp-test-20250927-svc
spec:
 ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 31111
 selector:
   app: myapp-test
 type: NodePort
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vim templates/deployment.yaml
1
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: myapp-test
 name: myapp-test-202401110926-deploy
spec:
 replicas: 5
 selector:
   matchLabels:
     app: myapp-test
 template:
   metadata:
     labels:
       app: myapp-test
   spec:
     containers:
      - image: wangyanglinux/myapp:v1.0
        name: myapp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 发布部署
helm install myapp myapp/
1
2

# 关键功能

vim templates/NOTES.txt
1
1、这是一个测试的 myapp chart
2、myapp release 名字:myapp-test-{{ now | date "20060102030405" }}-deploy
3、service 名字:myapp-test-{{ now | date "20060102030405" }}-svc
-----------------------------------------------------------------
1
2
3
4
vim templates/deployment.yaml
1
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: myapp-test
 name: myapp-test-{{ now | date "20060102030405" }}-deploy
spec:
 replicas: {{ .Values.replicaCount }}
 selector:
   matchLabels:
     app: myapp-test
 template:
   metadata:
     labels:
       app: myapp-test
   spec:
     containers:
      - image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
        name: myapp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
vim templates/service.yaml
1
apiVersion: v1
kind: Service
metadata:
 labels:
   app: myapp-test
 name: myapp-test-{{ now | date "20060102030405" }}-svc
spec:
 ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
    {{- if eq .Values.service.type "NodePort" }}
    nodePort: {{.Values.service.nodeport }}
    {{- end }}
 selector:
   app: myapp-test
 type: {{ .Values.service.type | quote }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vim values.yaml
1
# Default values for myapp.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 5
image:
 repository: wangyanglinux/myapp
 tag: "v1.0"
service:
 type: NodePort
 nodeport: 32321
1
2
3
4
5
6
7
8
9
10

# ingress-nginx

Ingress-NGINX 是 Kubernetes 官方维护的 Ingress Controller,基于 NGINX 反向代理。

它的作用是:

  • 把集群外部的请求(HTTP/HTTPS)转发到集群内部的 Service/Pod;

  • 支持域名、路径、TLS、流量控制等功能。

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm pull ingress-nginx/ingress-nginx
tar -zxvf ingress-nginx-4.13.2.tgz
修改 values.yaml文件的说明:
修改 hostNetwork的值为 true
dnsPolicy的值改为:ClusterFirstWithHostNet
kind类型更改为:DaemonSet
关闭所有镜像的 digest
ingressClassResource.default=true
1
2
3
4
5
6
7
8
9
10
kubectl create ns ingress
helm install ingress-nginx -n ingress ./ingress-nginx -f ingress-nginx/values.yaml
kubectl get pod -n ingress -o wide
1
2
3

# Ingress HTTP 代理访问

apiVersion: apps/v1
kind: Deployment
metadata:
 name: ingress-httpproxy-www1
spec:
 replicas: 2
 selector:
   matchLabels:
     hostname: www1
 template:
   metadata:
     labels:
       hostname: www1
   spec:
     containers:
     - name: nginx
       image: wangyanglinux/myapp:v1.0
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
 name: ingress-httpproxy-www1
spec:
 ports:
 - port: 80
   targetPort: 80
   protocol: TCP
 selector:
   hostname: www1
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: ingress-httpproxy-www1
spec:
 ingressClassName: nginx
 rules:
 - host: www.zmyz123456.com
   http:
     paths:
     - path: /
       pathType: Prefix
       backend:
         service:
           name: ingress-httpproxy-www1
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

# Ingress HTTPS 代理访问

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
kubectl create secret tls ingress-nginx-tls  --key tls.key --cert tls.crt
1
2
apiVersion: apps/v1
kind: Deployment
metadata:
 name: ingress-httpproxy-ssl
spec:
 replicas: 2
 selector:
   matchLabels:
     hostname: ssl
 template:
   metadata:
     labels:
       hostname: ssl
   spec:
     containers:
     - name: nginx
       image: wangyanglinux/myapp:v3.0
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
 name: ingress-httpproxy-ssl
spec:
 ports:
 - port: 80
   targetPort: 80
   protocol: TCP
 selector:
   hostname: ssl
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: networking.k8s.io/v1
kind: Ingress
metadata:
 name: ingress-httpproxy-ssl
 namespace: default
 annotations:
   nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
 ingressClassName: nginx
 rules:
 - host: ssl.xinxianghf.com
   http:
     paths:
     - path: /
       pathType: Prefix
       backend:
         service:
           name: ingress-httpproxy-ssl
           port:
             number: 80
 tls:
 - hosts:
   - ssl.xinxianghf.com
   secretName: ingress-nginx-tls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# Ingress BasicAuth 代理

http 认证文件创建

apt -y install httpd-tools
htpasswd -c auth zsan
kubectl create secret generic ingress-basic-auth --from-file=auth
1
2
3
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: ingress-with-auth
 annotations:
   nginx.ingress.kubernetes.io/auth-type: basic
   nginx.ingress.kubernetes.io/auth-secret: ingress-basic-auth
   nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - zsan'
spec:
 ingressClassName: nginx
 rules:
 - host: auth.zsan.com
   http:
     paths:
     - path: /
       pathType: ImplementationSpecific
       backend:
         service:
           name: ingress-httpproxy-auth
           port:
             number: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# Ingress-nginx 域名重定向

作用: 重定向是指服务器向客户端发出一个新的URL,让客户端进行新的请求。客户端会收到一个HTTP 3xx状态码,然后根据其中的重定向地址进行新的请求。这意味着客户端会知道发生了重定向,它会发起新的请求。 示例: 比如你有一个网站的旧地址是http://example.com,但是你希望所有的请求都转发到https://example.com,这时你就可以使用重定向将所有的HTTP请求重定向到HTTPS。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: redirect.zsan.com
 namespace: default
 annotations:
   kubernetes.io/ingress.class: "nginx"
   nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com
   nginx.ingress.kubernetes.io/permanent-redirect-code: '301'
spec:
 ingressClassName: "nginx"
 rules:   
  - host: redirect.zsan.com
    http:
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Ingress-nginx 重写

作用: 重写是指修改请求的路径,但是客户端不会察觉到这个变化,它仅在服务器内部发生。在Kubernetes 中,可以通过 Ingress 的注解来配置重写规则。 示例: 比如你有一个服务部署在 /v1路径下,但是你希望用户访问时不需要输入 /v1,那么你可以使用重写将请求从根路径 /重写到 /v1。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: rew.zsan.com
 namespace: default
 annotations:
   nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
 ingressClassName: "nginx"
 rules:
 - host: rew.zsan.com
   http:
     paths:
     - path: /api(/|$)(.*)
       pathType: ImplementationSpecific
       backend:
         service:
           name: www1svc
           port:
             number: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

重写和重定向区别

  • 影响范围: Rewrite 只在服务器内部修改请求路径,不会影响到客户端,而 Redirect 则会向客户端发送一个新的 URL,让客户端发起新的请求。

  • 状态码: Rewrite 不涉及状态码的改变,而 Redirect 会向客户端发送一个重定向的 HTTP 状态码(例如 301 永久重定向、302 临时重定向等)。

  • 可见性: Rewrite 对于客户端来说是透明的,而 Redirect 则会告知客户端发生了重定向。

    在选择使用 Rewrite 还是 Redirect 时,需要根据具体的需求来决定。如果你希望在不修改客户端请求的情况下修改路径,那么使用 Rewrite;如果你希望客户端知道发生了重定向,并且根据新的 URL 进行新的请求,那么使用 Redirect。

# Ingress-nginx 默认错误后端

# 修改values.yaml
defaultBackend:
 enabled: true
 name: defaultbackend
 image:
   registry: docker.io
   image: wangyanglinux/tools
   tag: "errweb1.0"
 port: 80
1
2
3
4
5
6
7
8
9

# Ingress-nginx 定制错误后端

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: errcode
 name: errcode
spec:
 replicas: 1
 selector:
   matchLabels:
     app: errcode
 template:
  metadata:
    labels:
      app: errcode
  spec:
    containers:
    - image: wangyanglinux/tools:errweb1.0
      name: tools
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: errcode
 name: errcode
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: errcode
 type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: errtest
 name: errtest
spec:
 replicas: 1
 selector:
   matchLabels:
     app: errtest
 template:
   metadata:
     labels:
       app: errtest
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: tools
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: errtest
 name: errtest
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: errtest
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: err.zsan.com
 namespace: default
 annotations:
   nginx.ingress.kubernetes.io/default-backend: 'errcode'
   nginx.ingress.kubernetes.io/custom-http-errors: "404,415"
spec:
 rules:
 - host: err.zsan.com
   http:
     paths:
     - path: /
       pathType: Prefix
       backend:
         service:
           name: errtest
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

# Ingress-nginx snippet

kubectl edit cm ingress-nginx-controller -n ingress
 data:
   allow-snippet-annotations: "true"
1
2
3
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: snippet
 name: snippet
spec:
 replicas: 1
 selector:
   matchLabels:
     app: snippet
 template:
   metadata:
     labels:
       app: snippet
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: tools
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: snippet
 name: snippet
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: snippet
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: snippet.zsan.com
 namespace: default
 annotations:
   nginx.ingress.kubernetes.io/server-snippet: |
     set $agentflag 0;
     if ($http_user_agent ~* "(Android|IPhone)") {
       set $agentflag 1;
     }
     if ($agentflag = 1) {
       return 302 http://www.baidu.com;
     }
spec:
 rules:
 - host: snippet.zsan.com
   http:
     paths:
     - path: /
       pathType: Prefix
       backend:
         service:
           name: snippet
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
curl snippet.zsan.com
curl snippet.zsan.com -H 'User-Agent: Android'  -I
1
2

# Ingress-nginx 黑白名单

黑白名单配置可以用configmap或annotations配置

  • 黑名单可以使用 ConfigMap 去配置
  • 白名单建议使用 Annotations 去配置

# configmap 添加黑名单

kubectl edit cm ingress-nginx-controller -n ingress
 data:
   allow-snippet-annotations: "true"
   block-cidrs: 192.168.10.12
1
2
3
4
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: test
 name: test-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: test
 template:
   metadata:
     labels:
       app: test
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: test
 name: test-svc
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: test
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: test.zsan.com
spec:
 rules:
 - host: test.zsan.com
   http:
     paths:
     - path: /
       pathType: Prefix
       backend:
         service:
           name: test-svc
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Annotations 添加黑名单

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: black
 name: black-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: black
 template:
   metadata:
     labels:
       app: black
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: black
 name: black-svc
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: black
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 annotations:
   nginx.ingress.kubernetes.io/server-snippet: |-
     deny 192.168.10.11;
     allow all;
 name: black.zsan.com
spec:
 rules:
 - host: black.zsan.com
   http:
     paths:
     - pathType: Prefix
       backend:
         service:
           name: black-svc
           port:
             number: 80
       path: /
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

Configmap 设置白名单

kubectl edit cm ingress-nginx-controller -n ingress
 apiVersion: v1
 data:
   allow-snippet-annotations: "true"
   whitelist-source-range: 192.168.10.11
1
2
3
4
5
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: test
 name: test-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: test
 template:
   metadata:
     labels:
       app: test
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: test
 name: test-svc
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: test
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: test.zsan.com
spec:
 rules:
 - host: test.zsan.com
   http:
     paths:
     - path: /
       pathType: Prefix
       backend:
         service:
           name: test-svc
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

annotations 添加白名单

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: white
 name: white-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: white
 template:
   metadata:
     labels:
       app: white
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: white
 name: white-svc
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: white
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 annotations:
   nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.10.11
 name: white.zsan.com
spec:
 rules:
 - host: white.zsan.com
   http:
     paths:
     - path: /
       pathType: Prefix
       backend:
         service:
           name: white-svc
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# Ingress-nginx 速率限制

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: speed
 name: speed-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: speed
 template:
   metadata:
     labels:
       app: speed
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: speed
 name: speed-svc
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: speed
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: speed.zsan.com
 namespace: default
spec:
 rules:   
 - host: speed.zsan.com
   http: 
     paths:
     - pathType: Prefix
       path: "/"
       backend:
         service:
           name: speed-svc
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
ab -c 10 -n 100 http://speed.zsan.com/ | grep requests
1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: speed.zsan.com
 namespace: default
 annotations:
   nginx.ingress.kubernetes.io/limit-connections: "1"
spec:
 rules:   
 - host: speed.zsan.com
   http: 
     paths:
     - pathType: Prefix
       path: "/"
       backend:
         service:
           name: speed-svc
           port:
             number: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Ingress-nginx 灰度发布

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: v1
 name: v1-deploy
spec:
 replicas: 10
 selector:
   matchLabels:
     app: v1
 template:
   metadata:
     labels:
       app: v1
   spec:
     containers:
     - image: wangyanglinux/myapp:v1.0
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: v1
 name: v1-svc
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: v1
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: v1.zsan.com
 namespace: default
spec:
 rules:   
 - host: svc.zsan.com
   http: 
     paths:
     - pathType: Prefix
       path: "/"
       backend:
         service:
           name: v1-svc
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: v2
 name: v2-deploy
spec:
 replicas: 10
 selector:
   matchLabels:
     app: v2
 template:
   metadata:
     labels:
       app: v2
   spec:
     containers:
     - image: wangyanglinux/myapp:v2.0
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: v2
 name: v2-svc
spec:
 ports:
 - name: 80-80
   port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app: v2
 type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: v2.zsan.com
 namespace: default
 annotations:
   nginx.ingress.kubernetes.io/canary: "true"
   nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
 rules:   
 - host: svc.zsan.com
   http: 
     paths:
     - pathType: Prefix
       path: "/"
       backend:
         service:
           name: v2-svc
           port:
             number: 80
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
for i in {1..100};do curl svc.xinxianghf.com >> sum;done
cat sum | sort | uniq -c
1
2

# ingress-nginx 代理后端 HTTPS 服务

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: proxyhttps
 name: proxyhttps-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: proxyhttps
 template:
   metadata:
     labels:
       app: proxyhttps
   spec:
     containers:
     - image: wangyanglinux/tools:httpsv1
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: proxyhttps
 name: proxyhttps-svc
spec:
 ports:
 - name: 443-443
   port: 443
   protocol: TCP
   targetPort: 443
 selector:
   app: proxyhttps
 type: ClusterIP
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 annotations:
   nginx.ingress.kubernetes.io/backend-protocol: HTTPS
 name: proxyhttps.zsan.com
 namespace: default
spec:
 rules:
 - host: proxyhttps.zsan.com
   http:
     paths:
     - backend:
         service:
           name: proxyhttps-svc
           port:
             number: 443
       path: /
       pathType: ImplementationSpecific
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# ingress-nginx 四层代理

kubectl edit ds -n ingress ingress-nginx-controller
   spec:
     containers:
      - args:
        - /nginx-ingress-controller
        - --tcp-services-configmap=$(POD_NAMESPACE)/nginx-ingress-tcp-configmap
1
2
3
4
5
6
apiVersion: v1
kind: ConfigMap
metadata:
 name: nginx-ingress-tcp-configmap
 namespace: ingress
data:
 "9000": "default/proxyhttps-svc:443"
1
2
3
4
5
6
7
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: proxyhttps
 name: proxyhttps-deploy
spec:
 replicas: 1
 selector:
   matchLabels:
     app: proxyhttps
 template:
   metadata:
     labels:
       app: proxyhttps
   spec:
     containers:
     - image: wangyanglinux/tools:httpsv1
       name: myapp
---
apiVersion: v1
kind: Service
metadata:
 labels:
   app: proxyhttps
 name: proxyhttps-svc
spec:
 ports:
 - name: 443-443
   port: 443
   protocol: TCP
   targetPort: 443
 selector:
   app: proxyhttps
 type: ClusterIP
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
33
34
35

ingress-nginx链路追踪

https://raw.githubusercontent.com/jaegertracing/jaeger-kubernetes/master/all-inone/jaeger-all-in-one-template.yml
1
kubectl edit cm ingress-nginx-controller -n ingress
   apiVersion: v1
   data:
     allow-snippet-annotations: "true"
     enable-opentracing: "true"   #开启链路追踪
     jaeger-collector-host: jaeger-agent.default.svc.cluster.local  #链路追踪的
svc名称
   kind: ConfigMap
   metadata:
     name: ingress-nginx-controller
     namespace: ingress-nginx
1
2
3
4
5
6
7
8
9
10
11
#Kubernetes
Harbor

← Harbor

最近更新
01
viper
12-20
02
Jenkins基础
12-19
03
Jenkins实践
12-19
更多文章>
Theme by Vdoing | Copyright © 2024-2025 The Fool
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式