Kubernetes 入门实战 Part2

2023-08-23 18:58:26 浏览数 (2)

17 多节点的 Kubernetes 集群

在腾讯云 TencentOS Server 3.1 (TK4) 下测试:

  • master SA3.MEDIUM4 2 核 4GB 5Mbps
  • worker S5.SMALL2 1 核 2GB 1Mbps
  • worker S5.SMALL2 1 核 2GB 1Mbps
代码语言:javascript复制
# 修改源 https://mirrors.cloud.tencent.com/
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.cloud.tencent.com/repo/centos7_base.repo
yum clean all
yum makecache

# install docker
yum remove docker 
                  docker-client 
                  docker-client-latest 
                  docker-common 
                  docker-latest 
                  docker-latest-logrotate 
                  docker-logrotate 
                  docker-engine

yum install -y yum-utils

yum-config-manager 
    --add-repo 
    https://download.docker.com/linux/centos/docker-ce.repo

yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

systemctl start docker
docker -v
docker run hello-world

一些准备工作:

代码语言:javascript复制
# 改主机名
vi /etc/hostname
# reboot
代码语言:javascript复制
# 把 cgroup 的驱动程序改成 systemd
# 使用 Docker 作为 Kubernetes 的底层支持
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

systemctl enable docker
systemctl daemon-reload
systemctl restart docker
docker version
代码语言:javascript复制
# https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/
# 转发 IPv4 并让 iptables 看到桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# check
lsmod | grep br_netfilter
lsmod | grep overlay

# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# 应用 sysctl 参数而不重新启动
sudo sysctl --system

sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
# net.bridge.bridge-nf-call-iptables = 1
# net.bridge.bridge-nf-call-ip6tables = 1
# net.ipv4.ip_forward = 1
代码语言:javascript复制
# 关闭 Linux 的 swap 分区
swapoff -a
sed -ri '/sswaps/s/^#?/#/' /etc/fstab
代码语言:javascript复制
# https://developer.aliyun.com/mirror/kubernetes
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.cloud.tencent.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
EOF

yum clean all
yum makecache

# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

# 新版本搞不定
# yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes --nogpgcheck

yum --showduplicate list kubelet
yum install -y kubelet-1.23.16-0 kubeadm-1.23.16-0 kubectl-1.23.16-0 --disableexcludes=kubernetes --nogpgcheck

systemctl enable --now kubelet

kubeadm version
kubectl version --output=yaml
kubelet --version

下载 Kubernetes 组件镜像:

代码语言:javascript复制
# kubeadm config images list
kubeadm config images list --kubernetes-version v1.23.16

安装 Master 节点:

代码语言:javascript复制
vim /etc/containerd/config.toml
#disabled_plugins = ["cri"]

systemctl enable containerd
systemctl restart containerd
systemctl status containerd

systemctl enable kubelet.service
systemctl restart kubelet
systemctl status kubelet

containerd config default > /etc/containerd/config.toml

yum install -y nc
nc 127.0.0.1 6443

kubeadm init -h
kubeadm reset -f
rm -rf ~/.kube/config

kubeadm init 
    --image-repository=registry.aliyuncs.com/google_containers 
    --pod-network-cidr=10.10.0.0/16 
    --kubernetes-version=v1.23.16 
    --v=9

# Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
#   https://kubernetes.io/docs/concepts/cluster-administration/addons/
代码语言:javascript复制
# success
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

export KUBECONFIG=/etc/kubernetes/admin.conf
代码语言:javascript复制
kubectl get node
# NAME     STATUS     ROLES                  AGE    VERSION
# master   NotReady   control-plane,master   2m4s   v1.23.16
代码语言:javascript复制
# dubug
systemctl restart docker
systemctl restart kubelet
systemctl restart containerd
journalctl -xeu kubelet
crictr ps -a
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps -a | grep kube | grep -v pause

kubectl get pods -n kube-system
kubectl describe pods -n kube-system
代码语言:javascript复制
# Flannel 网络插件 https://github.com/flannel-io/flannel/tree/master
# curl https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml --output kube-flannel.yml
#  net-conf.json: |
#     {
#       "Network": "10.10.0.0/16",
#       "Backend": {
#         "Type": "vxlan"
#       }
#     }
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
kubectl get node
# NAME     STATUS   ROLES                  AGE   VERSION
# master   Ready    control-plane,master   14h   v1.23.16
代码语言:javascript复制
# show join command in control-plane
kubeadm token create --print-join-command
# work join; 云服务记得开放入站端口
telnet 172.21.0.5 6443
systemctl enable kubelet.service
kubeadm join 172.21.0.5:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx --v=9
# check in control-plane
kubectl get nodes
# NAME            STATUS   ROLES                  AGE     VERSION
# master          Ready    control-plane,master   14h     v1.23.16
# vm-0-9-centos   Ready    <none>                 3m27s   v1.23.16
代码语言:javascript复制
# run nginx
kubectl run ngx --image=nginx:alpine
kubectl get pod -o wide
# NAME   READY   STATUS    RESTARTS   AGE   IP          NODE      NOMINATED NODE   READINESS GATES
# ngx    1/1     Running   0          52m   10.10.1.2   woker01   <none>           <none>

18 Deployment 部署应用

“单一职责”和“对象组合”。既然 Pod 管理不了自己,那么我们就再创建一个新的对象,由它来管理 Pod,采用和 Job/CronJob 一样的形式——“对象套对象”。

代码语言:javascript复制
kubectl api-resources

export out="--dry-run=client -o yaml"
kubectl create deploy ngx-dep --image=nginx:alpine $out > ngx-dep.yml
vim ngx-dep.yml
代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: ngx-dep
  name: ngx-dep
spec:
  # 定义了 Pod 的“期望数量”,Kubernetes 会自动维护 Pod 数量到正常水平
  replicas: 2
  # 定义了基于 labels 筛选 Pod 的规则,它必须与 template 里 Pod 的 labels 一致
  selector:
    matchLabels:
      app: ngx-dep
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      # 贴标签
      labels:
        app: ngx-dep
    spec:
      containers:
        - image: nginx:alpine
          name: nginx
          resources: {}
status: {}

Deployment 实际上并不“持有”Pod 对象,它只是帮助 Pod 对象能够有足够的副本数量运行。

通过标签这种设计,Kubernetes 就解除了 Deployment 和模板里 Pod 的强绑定,把组合关系变成了“弱引用”。

代码语言:javascript复制
# replicas: 2
kubectl apply -f ngx-dep.yml

kubectl get deploy
# NAME      READY   UP-TO-DATE   AVAILABLE   AGE
# ngx-dep   2/2     2            2           57s
kubectl get pod
# NAME                      READY   STATUS    RESTARTS   AGE
# ngx-dep-bfbb5f64b-96scb   1/1     Running   0          3m20s
# ngx-dep-bfbb5f64b-qnzbh   1/1     Running   0          3m20s
  • READY:运行的 Pod 数量,当前数量/期望数量。
  • UP-TO-DATE:当前已经更新到最新状态的 Pod 数量。
  • AVAILABLE:不仅要求已经运行,还必须是健康状态,能够正常对外提供服务,它才是我们最关心的 Deployment 指标。
  • AGE:从创建到现在所经过的时间。
代码语言:javascript复制
# 测试自启恢复
kubectl delete pod ngx-dep-bfbb5f64b-qnzbh
kubectl get pod
# NAME                      READY   STATUS    RESTARTS   AGE
# ngx-dep-bfbb5f64b-7n724   1/1     Running   0          33s
# ngx-dep-bfbb5f64b-96scb   1/1     Running   0          4m52s

# 测试伸缩
kubectl scale --replicas=5 deploy ngx-dep
kubectl get pod
# NAME                      READY   STATUS    RESTARTS   AGE
# ngx-dep-bfbb5f64b-7n724   1/1     Running   0          77s
# ngx-dep-bfbb5f64b-7xhbs   1/1     Running   0          7s
# ngx-dep-bfbb5f64b-96scb   1/1     Running   0          5m36s
# ngx-dep-bfbb5f64b-97qp5   1/1     Running   0          7s
# ngx-dep-bfbb5f64b-vjn4q   1/1     Running   0          7s
代码语言:javascript复制
# 筛选标签 ==、!=、in、notin
kubectl get pod -l app=nginx
kubectl get pod -l 'app in (ngx, nginx, ngx-dep)'

19 DaemonSet 看门狗

在 Deployment 看来,Pod 的运行环境与功能是无关的,只要 Pod 的数量足够,应用程序应该会正常工作。

有些场景下,要在集群里的每个节点上都运行 Pod,也就是说 Pod 的数量与节点数量保持同步。防止在集群里漂移。

DaemonSet 的目标是在集群的每个节点上运行且仅运行一个 Pod。

代码语言:javascript复制
kubectl api-resources
代码语言:javascript复制
# export out="--dry-run=client -o yaml"
# kubectl create deploy redis-ds --image=redis:5-alpine $out
# kind modify DaemonSet, delete spec.replicas
# https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/
# vim redis-ds.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: redis-ds
  labels:
    app: redis-ds
spec:
  # 和 deplayment 比没有 replicas
  selector:
    matchLabels:
      name: redis-ds
  template:
    metadata:
      labels:
        name: redis-ds
    spec:
      containers:
        - image: redis:5-alpine
          name: redis
          ports:
            - containerPort: 6379
代码语言:javascript复制
kubectl apply -f redis-ds.yml
kubectl get ds
# NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
# redis-ds   2         2         2       2            2           <none>          30m
kubectl get pod -o wide
# 两个 worker 的场景
# NAME                      READY   STATUS    RESTARTS   AGE   IP           NODE      NOMINATED NODE   READINESS GATES
# redis-ds-9r96k            1/1     Running   0          2m52s   10.10.3.2    woker02   <none>           <none>
# redis-ds-hdl28            1/1     Running   0          21m     10.10.1.11   woker01   <none>           <none>
# Master 节点却被排除在外了

污点(taint)作用也是给节点“贴标签”。容忍度(toleration)Pod 能否“容忍”污点。

代码语言:javascript复制
kubectl describe node master
# Taints:             node-role.kubernetes.io/master:NoSchedule
# 污点会拒绝 Pod 调度到本节点上运行
kubectl describe node woker01
# Taints:             <none>
代码语言:javascript复制
# - 出掉 master 污点
kubectl taint node master node-role.kubernetes.io/master:NoSchedule-
# NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
# redis-ds   3         3         3       3            3           <none>          31m
代码语言:javascript复制
# Pod 添加 tolerations
# kubectl explain ds.spec.template.spec.tolerations
# vim redis-ds-t.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: redis-ds-t
  labels:
    app: redis-ds-t
spec:
  # 和 deplayment 比没有 replicas
  selector:
    matchLabels:
      name: redis-ds-t
  template:
    metadata:
      labels:
        name: redis-ds-t
    spec:
      containers:
        - image: redis:5-alpine
          name: redis
          ports:
            - containerPort: 6379
      # 容忍 node-role.kubernetes.io/master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
          operator: Exists
代码语言:javascript复制
kubectl apply -f redis-ds-t.yml
kubectl get ds
# NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
# redis-ds     2         2         2       2            2           <none>          41m
# redis-ds-t   3         3         3       3            3           <none>          6s
# 差别在 master
kubectl get pod -o wide
# NAME                      READY   STATUS    RESTARTS   AGE   IP           NODE      NOMINATED NODE   READINESS GATES
# redis-ds-9r96k            1/1     Running   0          23m   10.10.3.2    woker02   <none>           <none>
# redis-ds-hdl28            1/1     Running   0          42m   10.10.1.11   woker01   <none>           <none>
# redis-ds-t-4mptv          1/1     Running   0          80s   10.10.3.4    woker02   <none>           <none>
# redis-ds-t-dpcl8          1/1     Running   0          80s   10.10.1.12   woker01   <none>           <none>
# redis-ds-t-kdjmn          1/1     Running   0          80s   10.10.0.6    master    <none>           <none>

https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/

静态 Pod:

代码语言:javascript复制
ll -a /etc/kubernetes/manifests
# -rw------- 1 root root 2274 Feb 22 12:47 etcd.yaml
# -rw------- 1 root root 3358 Feb 22 12:47 kube-apiserver.yaml
# -rw------- 1 root root 2878 Feb 22 12:47 kube-controller-manager.yaml
# -rw------- 1 root root 1465 Feb 22 12:47 kube-scheduler.yaml

Kubernetes 的 4 个核心组件 apiserver、etcd、scheduler、controller-manager 原来都以静态 Pod 的形式存在的,这也是为什么它们能够先于 Kubernetes 集群启动的原因。

kubelet 会定期检查目录里的文件。

代码语言:javascript复制
# flannel 就是一个 DaemonSet
kubectl get ns
kubectl get ds -n kube-flannel
# NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
# kube-flannel-ds   3         3         3       3            3           <none>          3h54m

20 Service 服务发现

由 kube-proxy 控制的四层负载均衡,在 TCP/IP 协议栈上转发流量。

Pod 的生命周期很短暂,会不停地创建销毁,所以就需要用 Service 来实现负载均衡,它由 Kubernetes 分配固定的 IP 地址,能够屏蔽后端的 Pod 变化。

代码语言:javascript复制
export out="--dry-run=client -o yaml"
kubectl expose deploy ngx-dep --port=80 --target-port=80 $ou
代码语言:javascript复制
# vim ngx-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: ngx-dep
status:
  loadBalancer: {}

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: ngx-conf
data:
  default.conf: |
    server {
      listen 80;
      location / {
        default_type text/plain;
        return 200
          'srv : $server_addr:$server_portnhost: $hostnamenuri : $request_method $host $request_urindate: $time_iso8601n';
      }
    }

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ngx-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ngx-dep
  template:
    metadata:
      labels:
        app: ngx-dep
    spec:
      volumes:
        - name: ngx-conf-vol
          configMap:
            name: ngx-conf
      containers:
        - image: nginx:alpine
          name: nginx
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: /etc/nginx/conf.d
              name: ngx-conf-vol
代码语言:javascript复制
kubectl apply -f ngx-svc.yml
kubectl get svc
# NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
# kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   5h10m
# ngx-svc      ClusterIP   10.109.131.132   <none>        80/TCP    35s
# 虚地址 10.109.131.132
kubectl describe svc ngx-svc
# Name:              ngx-svc
# Namespace:         default
# Labels:            <none>
# Annotations:       <none>
# Selector:          app=ngx-dep
# Type:              ClusterIP
# IP Family Policy:  SingleStack
# IP Families:       IPv4
# IP:                10.109.131.132
# IPs:               10.109.131.132
# Port:              <unset>  80/TCP
# TargetPort:        80/TCP
# Endpoints:         10.10.1.13:80,10.10.3.5:80
# Session Affinity:  None
# Events:            <none>
kubectl get pod -o wide
NAME                       READY   STATUS    RESTARTS   AGE    IP           NODE
ngx-dep-6796688696-cwm8f   1/1     Running   0          2m4s   10.10.3.5    woker02
ngx-dep-6796688696-khjnv   1/1     Running   0          2m2s   10.10.1.13   woker01
# same Endpoints

# 因为 Service、 Pod 的 IP 地址都是 Kubernetes 集群的内部网段
#   所以我们需要用 kubectl exec 进入到 Pod 内部
kubectl exec -it ngx-dep-6796688696-cwm8f -- sh
curl 10.109.131.132
# srv : 10.10.3.5:80
# host: ngx-dep-6796688696-cwm8f
# uri : GET 10.109.131.132 /
# date: 2023-02-22T10:09:49 00:00
curl 10.109.131.132
# srv : 10.10.1.13:80
# host: ngx-dep-6796688696-khjnv
# uri : GET 10.109.131.132 /
# date: 2023-02-22T10:09:50 00:00

# 测试恢复
kubectl delete pod ngx-dep-6796688696-khjnv
kubectl describe svc ngx-svc
# Endpoints:         10.10.1.14:80,10.10.3.5:80
# 之前是 10.10.1.13:80,10.10.3.5:80

# 测试扩容
kubectl scale --replicas=5 deploy ngx-dep
kubectl describe svc ngx-svc
# Endpoints:         10.10.1.14:80,10.10.1.15:80,10.10.3.5:80   2 more...

Service 对象的域名完全形式是 对象.名字空间.svc.cluster.local,但很多时候也可以省略后面的部分,直接写 对象.名字空间 甚至 对象名 就足够了,默认会使用对象所在的名字空间(比如这里就是 default)。

代码语言:javascript复制
# Name:              ngx-svc
# Namespace:         default
kubectl exec -it ngx-dep-6796688696-cwm8f -- sh
curl ngx-svc
# srv : 10.10.3.5:80
# host: ngx-dep-6796688696-cwm8f
# uri : GET ngx-svc /
# date: 2023-02-22T10:19:25 00:00
curl ngx-svc.default
# srv : 10.10.3.6:80
# host: ngx-dep-6796688696-lpcfs
# uri : GET ngx-svc.default /
# date: 2023-02-22T10:19:41 00:00
curl ngx-svc.default.svc.cluster.local
# srv : 10.10.3.5:80
# host: ngx-dep-6796688696-cwm8f
# uri : GET ngx-svc.default.svc.cluster.local /
# date: 2023-02-22T10:20:04 00:00

Pod 分配了域名:IP 地址.名字空间.pod.cluster.local IP 地址 . 改成 -。

代码语言:javascript复制
# kubectl explain svc.spec.type
# vim ngx-svc.yml
  ...
  type: NodePort
代码语言:javascript复制
kubectl apply -f ngx-svc.yml
kubectl get svc
# NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
# kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        5h56m
# ngx-svc      NodePort    10.109.131.132   <none>        80:30916/TCP   46m
# Service 的默认类型是“ClusterIP”,只能在集群内部访问,
#   如果改成“NodePort”,就会在节点上开启一个随机端口号,让外界也能够访问内部的服务。
curl localhost:30916
# srv : 10.10.1.15:80
# host: ngx-dep-6796688696-l6skl
# uri : GET localhost /
# date: 2023-02-22T10:48:32 00:00

21 Ingress 流量总管

Service 本身是没有服务能力的,它只是一些 iptables 规则,真正配置、应用这些规则的实际上是节点里的 kube-proxy 组件。

Ingress 也只是一些 HTTP 路由规则的集合,相当于一份静态的描述文件,真正要把这些规则在集群里实施运行,还需要有另外一个东西,这就是 Ingress Controller,它的作用就相当于 Service 的 kube-proxy,能够读取、应用 Ingress 规则,处理、调度流量。

Ingress Class 是插在 Ingress 和 Ingress Controller 中间,作为流量规则和控制器的协调人,解除了 Ingress 和 Ingress Controller 的强绑定关系。

Kubernetes 用户可以转向管理 Ingress Class,用它来定义不同的业务逻辑分组,简化 Ingress 规则的复杂度。

代码语言:javascript复制
export out="--dry-run=client -o yaml"
kubectl create ing ngx-ing --rule="ngx.test/=ngx-svc:80" --class=ngx-ink $out
代码语言:javascript复制
# vim ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  creationTimestamp: null
  name: ngx-ing
spec:
  ingressClassName: ngx-ink
  rules:
    - host: ngx.test
      http:
        # 路径的匹配方式
        paths:
          - backend:
              service:
                name: ngx-svc
                port:
                  number: 80
            path: /
            # 精确匹配(Exact)或前缀匹配(Prefix)
            pathType: Exact
status:
  loadBalancer: {}

---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: ngx-ink
spec:
  controller: nginx.org/ingress-controller
代码语言:javascript复制
kubectl apply -f ingress.yml
# NAME      CONTROLLER                     PARAMETERS   AGE
# ngx-ink   nginx.org/ingress-controller   <none>       15s
kubectl get ing
# NAME      CLASS     HOSTS      ADDRESS   PORTS   AGE
# ngx-ing   ngx-ink   ngx.test             80      84s
kubectl describe ing ngx-ing
# Name:             ngx-ing
# Labels:           <none>
# Namespace:        default
# Address:
# Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
# Rules:
#   Host        Path  Backends
#   ----        ----  --------
#   ngx.test
#               /   ngx-svc:80 (10.10.1.14:80,10.10.1.15:80)
# Annotations:  <none>
# Events:       <none>

在 Kubernetes 里使用 Ingress Controller:

https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/

代码语言:javascript复制
git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v3.0.2
cd kubernetes-ingress/deployments

# Configure RBAC
# 为Ingress控制器创建一个命名空间和一个服务账户
kubectl apply -f common/ns-and-sa.yaml
# 为服务账户创建一个集群角色和集群角色绑定
kubectl apply -f rbac/rbac.yaml

# Create Common Resources
# 为NGINX的默认服务器创建一个带有TLS证书和密钥的秘密
kubectl apply -f common/default-server-secret.yaml
# 创建一个 config map,用于定制NGINX配置。
kubectl apply -f common/nginx-config.yaml
# 创建一个IngressClass资源
kubectl apply -f common/ingress-class.yaml

# Create Custom Resources
# kubectl apply -f common/crds/
vim deployment/nginx-ingress.yaml
# args add:
# -enable-custom-resources=false

# Run the Ingress Controller
kubectl apply -f deployment/nginx-ingress.yaml

# check
kubectl get pods --namespace=nginx-ingress
# NAME                             READY   STATUS    RESTARTS   AGE
# nginx-ingress-5f98f8f5f9-nnkv7   1/1     Running   0          3m14s

# Get Access to the Ingress Controller
kubectl create -f service/nodeport.yaml
kubectl get service -n nginx-ingress
# NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
# nginx-ingress   NodePort   10.111.210.52   <none>        80:31754/TCP,443:30188/TCP   5s
代码语言:javascript复制
# debug
kubectl get IngressClass
kubectl get ing -n nginx-ingress
kubectl get deploy -n nginx-ingress
kubectl get pod -n nginx-ingress -o wide

kubectl describe service -n nginx-ingress -o wide
kubectl describe pod -n nginx-ingress
代码语言:javascript复制
# 命令kubectl port-forward,它可以直接把本地的端口映射到 Kubernetes 集群的某个 Pod 里
kubectl port-forward -n nginx-ingress nginx-ingress-5f98f8f5f9-nnkv7 8080:80 &

22 玩转 Kubernetes 2

Kubernetes 部署 WordPress:

代码语言:javascript复制
# vim wp-maria.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: maria-cm
data:
  DATABASE: "db"
  USER: "wp"
  PASSWORD: "123"
  ROOT_PASSWORD: "123"

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: maria-dep
  name: maria-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: maria-dep
  template:
    metadata:
      labels:
        app: maria-dep
    spec:
      containers:
        - image: mariadb:10
          name: mariadb
          ports:
            - containerPort: 3306
          envFrom:
            - prefix: "MARIADB_"
              configMapRef:
                name: maria-cm

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: maria-dep
  name: maria-svc
spec:
  ports:
    - port: 3306
      protocol: TCP
      targetPort: 3306
  selector:
    app: maria-dep
代码语言:javascript复制
kubectl apply -f wp-maria.yml
kubectl get pod
kubectl get deploy
kubectl get svc
代码语言:javascript复制
# vim wp-app.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: wp-cm
data:
  # DNS HOST
  HOST: "maria-svc"
  USER: "wp"
  PASSWORD: "123"
  NAME: "db"

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wp-dep
  name: wp-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: wp-dep
  template:
    metadata:
      labels:
        app: wp-dep
    spec:
      containers:
        - image: wordpress:5
          name: wordpress
          ports:
            - containerPort: 80
          envFrom:
            - prefix: "WORDPRESS_DB_"
              configMapRef:
                name: wp-cm

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: wp-dep
  name: wp-svc
spec:
  ports:
    - name: http80
      port: 80
      protocol: TCP
      targetPort: 80
      # 指定端口
      nodePort: 30088
  selector:
    app: wp-dep
  # NodePort
  type: NodePort
代码语言:javascript复制
kubectl apply -f wp-app.yml
kubectl get pod
kubectl get deploy
kubectl get svc

kubectl port-forward service/wp-svc 80:80 --address 0.0.0.0
代码语言:javascript复制
# vim wp-ing.yml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: wp-ink
spec:
  controller: nginx.org/ingress-controller

---
# kubectl create ing wp-ing --rule="wp.test/=wp-svc:80" --class=wp-ink $out
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: wp-ing
spec:
  ingressClassName: wp-ink
  rules:
    - host: wp.test
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: wp-svc
                port:
                  number: 80
代码语言:javascript复制
# vim wp-kic-dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wp-kic-dep
  namespace: nginx-ingress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wp-kic-dep
  template:
    metadata:
      labels:
        app: wp-kic-dep
    spec:
      # kubectl explain Deployment.spec.template.spec.serviceAccountName
      serviceAccountName: nginx-ingress
      # kubectl explain Deployment.spec.template.spec.hostNetwork
      hostNetwork: true
      containers:
        - image: nginx/nginx-ingress:3.0.2
          imagePullPolicy: IfNotPresent
          name: nginx-ingress
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
            - name: readiness-port
              containerPort: 8081
            - name: prometheus
              containerPort: 9113
          readinessProbe:
            httpGet:
              path: /nginx-ready
              port: readiness-port
            periodSeconds: 1
          securityContext:
            allowPrivilegeEscalation: true
            runAsUser: 101 #nginx
            runAsNonRoot: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          args:
            # 默认是 nginx
            - -ingress-class=wp-ink
            - -enable-custom-resources=false
            - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
            - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret

---
apiVersion: v1
kind: Service
metadata:
  name: wp-kic-svc
  namespace: nginx-ingress

spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
      nodePort: 30080

  selector:
    app: wp-kic-dep
  type: NodePort
代码语言:javascript复制
kubectl apply -f wp-ing.yml -f wp-kic-dep.yml

kubectl get ing
kubectl get ingressclass
kubectl get pod -n=nginx-ingress
kubectl describe pod -n=nginx-ingress
kubectl get deploy -n=nginx-ingress
kubectl get svc -n=nginx-ingress
代码语言:javascript复制
# 在服务器上
kubectl get pod -n=nginx-ingress -o=wide
# NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE
# wp-kic-dep-68579bc688-d64zs   1/1     Running   0          10m   172.21.0.9   woker01
curl 172.21.0.9 -H "HOST: wp.test"
代码语言:javascript复制
# 在服务器外
kubectl port-forward service/wp-kic-svc -n=nginx-ingress 80:80 --address 0.0.0.0

vim /etc/hosts
[master ip] wp.test
# 游览器访问 wp.test

23 中级篇实操总结

代码语言:javascript复制
# DaemonSet 模板生成
kubectl create deploy redis-ds --image=redis:5-alpine $out 
  | sed 's/Deployment/DaemonSet/g' - 
  | sed -e '/replicas/d' -

References

  • chronolaw/k8s_study | GitHub
  • nginx-ingress-controller Installation with Manifests | nginx.com

– EOF –

  • # kubernetes

0 人点赞