/

Kubernetes 入门实战 Part2

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
# 修改源 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

一些准备工作:

# 改主机名
vi /etc/hostname
# reboot
# 把 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
# 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
# 关闭 Linux 的 swap 分区
swapoff -a
sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
# 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 组件镜像:

# kubeadm config images list
kubeadm config images list --kubernetes-version v1.23.16

安装 Master 节点:

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/
# 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
kubectl get node
# NAME STATUS ROLES AGE VERSION
# master NotReady control-plane,master 2m4s v1.23.16
# 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
# 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
# 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
# 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 一样的形式——“对象套对象”。

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
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 的强绑定,把组合关系变成了“弱引用”。

# 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:从创建到现在所经过的时间。
# 测试自启恢复
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
# 筛选标签 ==、!=、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。

kubectl api-resources
# 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
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 能否“容忍”污点。

kubectl describe node master
# Taints: node-role.kubernetes.io/master:NoSchedule
# 污点会拒绝 Pod 调度到本节点上运行
kubectl describe node woker01
# Taints: <none>
# - 出掉 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
# 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
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:

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 会定期检查目录里的文件。

# 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 变化。

export out="--dry-run=client -o yaml"
kubectl expose deploy ngx-dep --port=80 --target-port=80 $ou
image
# 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_port\nhost: $hostname\nuri : $request_method $host $request_uri\ndate: $time_iso8601\n';
}
}

---
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
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)。

# 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 地址 . 改成 -。

# kubectl explain svc.spec.type
# vim ngx-svc.yml
...
type: NodePort
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
image

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 规则的复杂度。

export out="--dry-run=client -o yaml"
kubectl create ing ngx-ing --rule="ngx.test/=ngx-svc:80" --class=ngx-ink $out
# 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
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/

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
# 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
# 命令kubectl port-forward,它可以直接把本地的端口映射到 Kubernetes 集群的某个 Pod 里
kubectl port-forward -n nginx-ingress nginx-ingress-5f98f8f5f9-nnkv7 8080:80 &
image

22 玩转 Kubernetes 2

Kubernetes 部署 WordPress:

image
# 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
kubectl apply -f wp-maria.yml
kubectl get pod
kubectl get deploy
kubectl get svc
# 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
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
# 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
# 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
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
# 在服务器上
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"
# 在服务器外
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
image

23 中级篇实操总结

# DaemonSet 模板生成
kubectl create deploy redis-ds --image=redis:5-alpine $out \
| sed 's/Deployment/DaemonSet/g' - \
| sed -e '/replicas/d' -

References

– EOF –