1. 设置系统参数 – 允许路由转发,不对bridge的数据进行处理
2. 设置iptables的FORWARD链,Docker从1.13版本开始调整了默认的防火墙规则,禁用了iptables filter表中FOWARD链,这样会引起Kubernetes集群中跨Node的Pod无法通信。
3. Kubernetes 1.8开始要求关闭系统的Swap,如果不关闭,默认配置下kubelet将无法启动。可以通过kubelet的启动参数--fail-swap-on=false更改这个限制。
4. 通过kubectl命令获取secret,以及token,用于登录dashboard UI,基于RBAC(基于角色的访问控制)见附录
#关键字根据你创建的create来,比如admin,dashboard
原理:创建一个ServiceAccount,并将该SA绑定到cluster-admin这个ClusterRole角色上,就拥有了该角色的权限,而这个角色拥有整个集群的所有权限。
#这里还涉及一个https访问的问题,需要在master节点(这里要求dashboard部署在master节点上)生成自签名的证书,然后在kubernetes-dashboard.yaml文件中修改:
volumes:
- name: kubernetes-dashboard-certs
hostPath:
path: /usr/share/certs
type: Directory
自签名的步骤如下:
openssl genrsa -des3 -passout pass:x -out dashboard.pass.key 2048
openssl rsa -passin pass:x -in dashboard.pass.key -out dashboard.key
rm dashboard.pass.key
openssl req -new -key dashboard.key -out dashboard.csr
openssl x509 -req -sha256 -days 365 -in dashboard.csr -signkey dashboard.key -out dashboard.crt
#将dashboard.key dashboard.crt拷贝至/usr/share/certs目录即可。
5. 通过kubeadm init命令创建集群之后,会报错http://localhost:10255/healthz出错,发现是kubelet服务没有启动
需要创建kubelet.service.d目录,并在其下创建10-kubeadm.conf文件,内容如下:
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"
Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin"
Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt" # Value should match Docker daemon settings. # Defaults are "cgroupfs" for Debian/Ubuntu/OpenSUSE and "systemd" for Fedora/CentOS/RHEL
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs"
Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"
Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true"
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS
这里也可以直接通过命令从github上下载
curl -O "https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.0/build/debs/kubelet.service" #注意/usr/bin/kubelet路径问题
再创建kubelet.service.d目录,并从github上下载
curl -O "https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.0/build/debs/10-kubeadm.conf"
6. 集群部署成功之后,发送kubectl命令还是无法获取集群信息,这里需要export KUBECONFIG参数
为了简化,可以写在/etc/profile,并执行source /etc/profile使其生效,注意:master节点和node节点采用不一样的配置文件,权限不一样。
# master节点上 export KUBECONFIG=/etc/kubernetes/admin.conf
# node节点上 export KUBECONFIG=/etc/kubernetes/kubelet.conf
7. kubectl proxy命令目前来说,使用的场景是,自动化部署脚本中,需要远程部署Pod至Kubernetes集群,因为需要http访问,绕过https。
kubectl proxy --address='0.0.0.0' --port=8080 --accept-hosts='^*$'
这样在shell脚本中才可以执行: kubectl -s http://masterIp:8080 apply -f *.yaml
8. 通过kubeadm token命令生成一个forever的token,默认的24h,利于后续join新的节点到集群。
kubeadm token create --ttl=0
kubeadm join masterIp:6443 --token bhpmca.yz08394xcolahg0y --discovery-token-ca-cert-hash sha256:f2d058d7f6489dd71aba1c780adf4e7e24663a6db54e7e1fbc3ca079f616bd92
另外,如果忘记了sha256,这里也提供一个查询方法,如下:
#获取master上的ca.crt证书sha256编码hash值
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
9. 集群清理命令
# 删除节点
kubectl drain nodeName --delete-local-data --force --ignore-daemonsets
kubectl delete node nodeName
# 清理
kubeadm reset
ifconfig cni0 down
ip link delete cni0
ifconfig flannel.1 down
ip link delete flannel.1
rm -rf /var/lib/cni/
rm -rf /etc/kubernetes/
systemctl stop kubelet;
docker rm -f -v $(docker ps -q);
find /var/lib/kubelet | xargs -n 1 findmnt -n -t tmpfs -o TARGET -T | uniq | xargs -r umount -v;
rm -rf /var/lib/kubelet /var/lib/etcd;
# 记住要清理iptables
iptables -FXZ
10. 通过java -jar启动jar包项目时,出现服务发现失败的问题
比如在项目的rabbitmq.properties文件中定义了Kubernetes的serviceName来访问节点
但是如果是直接server.host=rabbitmq,程序中访问失败,但是查看dns,ping服务名ip显示都是正常
root@node:~/k8s# cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
root@node:~/k8s# ping rabbitmq
PING rabbitmq.default.svc.cluster.local (10.109.82.27): 56 data bytes
最终,通过server.host=rabbitmq.default,则访问正常,见附录2。
11. 通过netstat -npt | grep 30039 | wc -l查看端口连接个数
12. Node的隔离与恢复
apiVersion: v1
kind: Node
metadata:
name: masterNodename
labels:
xx.com/hostname: masterNodename
spec:
unschedulable: true
13. Node设置标签,将Pod调度指定Node
key=value
的 Node 上14. 应用的滚动升级
kubectl rolling-update redis-master --image=kubeguide/redis-master:2.0
kubectl rolling-update redis-master --image=kubeguide/redis-master:2.0 --rollback
以上是RC的滚动升级方式,目前有更好的Deployment资源管理:
1. 更新deployment,我们只需更新deployment里面的template,当我们更新deployment时,当有合适的Pod产生,k8s才会删除老的Pod,当老的Pod被删除足够多时,才会继续产生新的Pod。
2. 定义deployment时,与rolling update相关项
.spec.minReadySeconds: 新建的Pod状态为ready持续时间至少为它,才认为Pod Available(Ready),默认30s
.spec.strategy.rollingUpdate.maxSurge: 默认是desired Pods数的25%,Scale Up新的ReplicaSet时,允许的maxSurge,可以是整数或者百分比,向上取整
.spec.strategy.rollingUpdate.maxUnavailable: 默认为desired Pods数的25%,Scale Down旧的ReplicaSet时,允许的maxUnavailable,可以是整数或者百分比,向下取整
因此,在Deployment rollout时,需要保证Available(Ready) Pods数不低于 desired pods number - maxUnavailable; 保证所有的Pods数不多于 desired pods number + maxSurge。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 3
maxUnavailable: 2
replicas: 25
template:
kubectl set image deployment xxx-dep myregistry:5000/xxx=myregistry:5000/xxx:v2 --namespace=default
kubectl rollout undo deployment xxx-dep --namespace=default
kubectl rollout undo deployment xxx-dep --revision=1 --namespace=default
kubectl rollout history deployment xxx-dep --namespace=default
kubectl rollout history deployment xxx-dep --revision=2 --namespace=default
15. 修改k8s集群的端口范围,默认是30000-32767,为了不合其他应用冲突,通过修改配置/etc/kubernetes/manifests/kube-apiserver.yaml实现
16. 目前采用的版本是Kubernetes v1.10.0,以下是对应的镜像版本
k8s.gcr.io/kube-apiserver-amd64:v1.10.0
k8s.gcr.io/kube-scheduler-amd64:v1.10.0
k8s.gcr.io/kube-controller-manager-amd64:v1.10.0
k8s.gcr.io/etcd-amd64:v1.10.0
k8s.gcr.io/kube-proxy-amd64:v1.10.0
k8s.gcr.io/pause-amd64:3.1
quay.io/coreos/flannel:v0.10.0-amd64
k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.8
k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.8
k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.8
k8s.gcr.io/heapster-influxdb-amd64:v1.3.3
k8s.gcr.io/heapster-grafana-amd64:v4.4.3
k8s.gcr.io/heapster-amd64:v1.4.2
17. kubelet指定本地镜像
kubelet 修改配置以使用本地自定义pause镜像
cat > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf <"KUBELET_EXTRA_ARGS=--pod-infra-container-image=local.repo/google_containers/pause-amd64:3.1"
EOF
systemctl daemon-reload
systemctl restart kubelet
附录1. RBAC(Role-Base-Access-Control),基于角色的权限控制策略。
涉及ServiceAccount、Role、RoleBinding,Kubernetes集群中也有一个默认的ClusterRole、ClusterRoleBinding拥有所有权利的角色。
所以简单的做法是:创建一个ServiceAccount,让它通过ClusterRoleBinding绑定到ClusterRole(cluster-admin),则新创建的用户获得了集群的所有权限。
当然,在kubernetes集群中,最佳的做法是,为每一个应用程序的服务账户授予角色,确保该账户在指定命名空间下控制应用程序的运行。
例如:在tiller-world的namespace下创建tiller用户,通过RoleBinding绑定到一个自定义的Role上。
$ kubectl create namespace tiller-world
namespace "tiller-world" created
$ kubectl create serviceaccount tiller --namespace tiller-world
serviceaccount "tiller" created
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata:
name: tiller-manager
namespace: tiller-world
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["*"]
verbs: ["*"]
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata:
name: tiller-binding
namespace: tiller-world
subjects:
- kind: ServiceAccount
name: tiller
namespace: tiller-world
roleRef:
kind: Role
name: tiller-manager
apiGroup: rbac.authorization.k8s.io
RBAC虽然很灵活,但是它的缺点是没有提供顺序操作的机制,导致它无法应用到那些有严格操作次序的系统。
附录2. 服务发现
k8s将Service的名称当做域名注册到kube-dns,这样在集群中就可以通过serverName访问服务了。
kube-dns通过nslookup指令检查DNS查询服务的健康状态,pod中的容器查询DNS时是通过serverName.namespace子域名查询的,所以最好在serviceName后面加上namespace,避免可能的错误,例如: nslookup kubernetes.default
kube-dns支持的域名格式,具体为:
其中cluster_domain可以使用kubelet的--cluster-domain=SomeDomain参数进行设置,通常设置为:cluster.local
每个Pod中的/etc/resolv.conf文件中的参数:nameserver 10.96.0.10,对应就是kube-dns服务的ClusterIp,Pod的域名解析服务器,当然是通过kubelet的--cluster-dns参数设置的。
本文转自开源中国-Kubernetes相关的问题汇总