kube-proxy
我们知道容器的特点是快速创建、快速销毁,Kubernetes Pod和容器一样只具有临时的生命周期,一个Pod随时有可能被终止或者漂移,随着集群的状态变化而变化,一旦Pod变化,则该Pod提供的服务也就无法访问,如果直接访问Pod则无法实现服务的连续性和高可用性,因此显然不能使用Pod地址作为服务暴露端口。
解决这个问题的办法和传统数据中心解决无状态服务高可用的思路完全一样,通过负载均衡和VIP实现后端真实服务的自动转发、故障转移。
这个负载均衡在Kubernetes中称为Service,VIP即Service ClusterIP,因此可以认为Kubernetes的Service就是一个四层负载均衡,Kubernetes对应的还有七层负载均衡Ingress,本文仅介绍Kubernetes Service。
这个Service就是由kube-proxy实现的,ClusterIP不会因为Pod状态改变而变,需要注意的是VIP即ClusterIP是个假的IP,这个IP在整个集群中根本不存在,当然也就无法通过IP协议栈无法路由,底层underlay设备更无法感知这个IP的存在,因此ClusterIP只能是单主机(Host Only)作用域可见,这个IP在其他节点以及集群外均无法访问。
Kubernetes为了实现在集群所有的节点都能够访问Service,kube-proxy默认会在所有的Node节点都创建这个VIP并且实现负载
部署策略:
- 使用 kubeconfig 访问 apiserver 的安全端口;
- 在 KubeProxyConfiguration 类型的 yaml 文件配置主要参数;
- 使用 ipvs 代理模式;
01.创建Kube-proxy证书和私钥
cat > kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "China",
"L": "Beijing",
"O": "Kubernetes",
"OU": "Kubernetes",
"ST": "Beijing"
}
]
}
EOF
解释:
CN:指定该证书的 User 为 system:kube-proxy;
预定义的 RoleBinding system:node-proxier 将User system:kube-proxy 与Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
该证书只会被 kube-proxy 当做 client 证书使用,所以 hosts 字段为空。
创建 kube-proxy 凭证与私钥:
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-proxy-csr.json | cfssljson -bare kube-proxy
结果将产生以下两个文件:
kube-proxy-key.pem
kube-proxy.pem
02.创建 kube-proxy kubeconfig 文件
export KUBE_APISERVER="https://apiserver-p001.svc.gxd88.cn:6443"
-
设置集群参数
kubectl config set-cluster kubernetes \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=kube-proxy.kubeconfig
-
设置客户端认证参数
kubectl config set-credentials kube-proxy \ --client-certificate=kube-proxy.pem \ --client-key=kube-proxy-key.pem \ --embed-certs=true \ --kubeconfig=kube-proxy.kubeconfig
-
设置上下文参数
kubectl config set-context default \ --cluster=kubernetes \ --user=kube-proxy \ --kubeconfig=kube-proxy.kubeconfig
-
设置默认上下文
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
- 设置集群参数和客户端认证参数时 --embed-certs 都为 true,这会将 certificate-authority、client-certificate 和 client-key 指向的证书文件内容写入到生成的 kube-proxy.kubeconfig 文件中;
- kube-proxy.pem 证书中 CN 为 system:kube-proxy,kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
03.维护kube-proxy配置文件
同kubelet一样, kube-proxy中的很多参数已经废弃需要单独的配置文件支持, 你可以使用 --write-config-to 选项生成该配置文件
注意: 如果kubelet中配置了hostnameOverride那么kube-proxy也需要相同的配置
cat > /srv/kubernetes/conf/kube-proxy-config.yml <<EOF
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 10.40.61.116
clientConnection:
acceptContentTypes: ""
burst: 10
contentType: application/vnd.kubernetes.protobuf
kubeconfig: "/srv/kubernetes/kubeconfig/kube-proxy.kubeconfig"
qps: 5
clusterCIDR: "10.243.0.0/16"
configSyncPeriod: 15m0s
conntrack:
maxPerCore: 32768
min: 131072
tcpCloseWaitTimeout: 1h0m0s
tcpEstablishedTimeout: 24h0m0s
detectLocalMode: ""
enableProfiling: false
healthzBindAddress: 0.0.0.0:10256
hostnameOverride: "py-modelo2o08cn-p005.pek3.example.net"
iptables:
masqueradeAll: false
masqueradeBit: 14
minSyncPeriod: 0s
syncPeriod: 30s
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
strictARP: false
syncPeriod: 30s
tcpFinTimeout: 0s
tcpTimeout: 0s
udpTimeout: 0s
kind: KubeProxyConfiguration
metricsBindAddress: 127.0.0.1:10249
mode: "ipvs"
nodePortAddresses: null
oomScoreAdj: -999
portRange: ""
showHiddenMetricsForVersion: ""
udpIdleTimeout: 250ms
winkernel:
enableDSR: false
networkName: ""
sourceVip: ""
EOF
参数说明:
bindAddress
: 监听地址;
clientConnection.kubeconfig
: 连接 apiserver 的 kubeconfig 文件
clusterCIDR
: kube-proxy 根据 --cluster-cidr 判断集群内部和外部流量,指定 --cluster-cidr 或 --masquerade-all 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT;
hostnameOverride
: 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node,从而不会创建任何 ipvs 规则;
mode
: 使用 ipvs 模式。
04.使用systemd管理kube-proxy
根据实际情况替换--hostname-override
cat > /etc/systemd/system/kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
ExecStart=/srv/kubernetes/bin/kube-proxy \
--config=/srv/kubernetes/conf/kube-proxy-config.yml \
--v=2 \
--logtostderr=false \
--log-dir=/srv/kubernetes/log
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
05.启动/停止 kube-proxy
sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable kube-proxy.service
kube-proxy can be started and stopped as follows:
sudo systemctl start kube-proxy.service
sudo systemctl stop kube-proxy.service
06.验证
检查服务:
systemctl status kube-proxy|grep Active
Active: active (running) since 四 2020-04-16 15:46:21 CST; 1 day 22h ago
检查端口:
kube-proxy 监听 10249 和 10256 端口:
- 10249:对外提供 /metrics;
- 10256:对外提供 /healthz 的访问。
$ netstat -lnpt|grep kube-prox
tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 11562/kube-proxy
tcp6 0 0 :::10256 :::* LISTEN 11562/kube-proxy
07.测试
创建pod测试
kubectl run --image=nginx:1.17 nginx-app --port=80
创建service
kubectl expose deployment nginx-app --port=80 --name nginx-app
查看ipvs规则
$ ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.244.0.1:443 rr
-> 10.40.58.153:6443 Masq 1 0 0
-> 10.40.58.154:6443 Masq 1 0 0
-> 10.40.61.116:6443 Masq 1 0 0
TCP 10.244.155.238:80 rr
-> 10.243.104.2:80 Masq 1 0 0
Q&A
Q: 启动kube-proxy 日志文件一直报如下错误
proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[10 40 61 116 0 0 0 0 0 0 0 0 0 0 0 0]
proxier.go:1192] Failed to sync endpoint for service: 10.244.0.1:443/TCP, err: parseIP Error ip=[10 40 61 116 0 0 0 0 0 0 0 0 0 0 0 0]
网友评论