Kubernetes相关的问题汇总

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 1. 设置系统参数 – 允许路由转发,不对bridge的数据进行处理 net.bridge.bridge-nf-call-ip6tables=1 net.bridge.bridge-nf-call-iptables=1 net.ipv4.ip_forward=1 vm.swappiness=0 2. 设置iptables的FORWARD链,Docker从1.13版本开始调整了默认的防火墙规则,禁用了iptables filter表中FOWARD链,这样会引起Kubernetes集群中跨Node的Pod无法通信。

1. 设置系统参数 – 允许路由转发,不对bridge的数据进行处理


  • net.bridge.bridge-nf-call-ip6tables=1
  • net.bridge.bridge-nf-call-iptables=1
  • net.ipv4.ip_forward=1
  • vm.swappiness=0

2. 设置iptables的FORWARD链,Docker从1.13版本开始调整了默认的防火墙规则,禁用了iptables filter表中FOWARD链,这样会引起Kubernetes集群中跨Node的Pod无法通信。

  • iptables -P FORWARD ACCEPT
  • iptables -nvL #查看命令

3. Kubernetes 1.8开始要求关闭系统的Swap,如果不关闭,默认配置下kubelet将无法启动。可以通过kubelet的启动参数--fail-swap-on=false更改这个限制。

  • swapoff -a
  • free -mh #查看命令

4. 通过kubectl命令获取secret,以及token,用于登录dashboard UI,基于RBAC(基于角色的访问控制)见附录

  • kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin | awk '{print $1}')

#关键字根据你创建的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查看端口连接个数

  • apt-get install -y net-tools
  • netstat -anopt|grep 30039|wc -l

12. Node的隔离与恢复

  • kubectl replace -f unschedule_node.yaml
apiVersion: v1
kind: Node
metadata:
 name: masterNodename
 labels:
 xx.com/hostname: masterNodename
spec:
 unschedulable: true
  • kubectl patch node nodeName -p '{"spec":{"unschedulable":true}}'
  • 将某个Node脱离调度范围时,在其上运行的Pod并不会自动停止,管理员需要手动停止在该Node上运行的Pod

13. Node设置标签,将Pod调度指定Node

  • kubectl label nodes nodeName zone=north
  • kubectl label nodes nodeName disktype=ssd
  • kubectl get node --show-labels #查看节点label
  • Pod/Deployment的spec.spec.nodeSelector #指定将此 Pod 部署到具有 label key=value 的 Node 上
  • 注意:如果指定Pod的nodeSelector条件,且集群中不存在包含相应标签的Node时,即使还有其他可供调度的Node,这个Pod也最终会调度失败

14. 应用的滚动升级

  • Kubernetes提供了rolling-update(滚动升级),解决服务需要先全部停止然后逐步升级的方式导致的较长时间的服务不可用情况
  • 滚动升级通过执行kubectl rolling-update命令一键完成,该命令创建了一个新的RC,然后自动控制旧的RC中的Pod副本数量逐渐减少到0,同时新的RC中的Pod副本数量从0逐步增加到目标值,最终实现了Pod的升级。需要注意的是,系统要求新的RC需要与旧的RC在相同的命名空间(Namespace)内,即不能把别人的资产偷偷转移到自家名下
  • 以redis-master为例,假设当前运行的redis-master Pod是1.0版本,则现在需要升级到2.0版本
  1. RC的名字(name)不能与旧的RC的名字相同
  2. 在selector中应至少有一个Label与旧的RC的Label不同,以标识其为新的RC,例如:version: v2
  3. kubectl rolling-update redis-master -f redis-master-controller-v2.yaml
  4. 等所有新的Pod启动完成后,旧的Pod也被全部销毁,这样就完成了容器集群的更新。
  • 直接用kubectl rolling-update命令,加上--image参数指定新版镜像名称来完成Pod的滚动升级
  1. 执行的结果是旧的RC被删除,新的RC仍将使用旧的RC的名字
  2. 如果在更新过程中发现配置有误,则用户可以中断更新操作,并通过执行Kubectl rolling-update –rollback完成Pod版本的回滚
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实现

  • --service-cluster-ip-range=10.96.0.0/12
  • --service-node-port-range=1-65535
  • 修改kube-apiserver.yaml后,kube-apiserver自动重启,这是因为kubelet在监听着/etc/kubernetes/manifests目录下的文件变化并处理

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 <<EOF
[Service]
Environment="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支持的域名格式,具体为:<service_name>.<namespace>.svc.<cluster_domain>

其中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相关的问题汇总

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
3月前
|
Kubernetes 负载均衡 Linux
Kubernetes的应用
Kubernetes的应用
34 0
|
4天前
|
Kubernetes 前端开发 网络协议
Kubernetes服务
Kubernetes服务
15 0
Kubernetes服务
|
3月前
|
Kubernetes 监控 关系型数据库
了解Kubernetes
kubernetes入门
21 0
|
3月前
|
Kubernetes 负载均衡 应用服务中间件
Kubernetes
Kubernetes 版 ACK(Alibaba Cloud Container Service for Kubernetes)是阿里云提供的一种容器服务,它基于 Kubernetes 开源容器编排平台,为用户提供高效、可扩展的容器应用管理能力。ACK 可以帮助用户在云端轻松部署、管理和扩展容器化应用,同时提供了丰富的 Kubernetes 功能,例如自动扩展、滚动更新、负载均衡等。
35 1
|
8月前
|
Kubernetes 容器
Kubernetes的ExternalName详解
ExternalName类型的Service在Kubernetes中用于将外部服务(不是Kubernetes集群内的服务)映射到Kubernetes集群内的Service。 # 样例 其创建方法如下: ``` kind: Service apiVersion: v1 metadata: name: my-external-service namespace: cv-console-dev labels: app: my-external-service annotations: kubesphere.io/creator: sunjq kubesph
160 0
|
9月前
|
运维 Kubernetes 安全
Kubernetes 之 Egress 思考
“网络周边安全”是任何一个企业运维团队所必须关注的重点。当我们谈到网络界面控制时,我们往往潜意识地先会想到入站安全(入口)。然而,基于流量的运作,例如,何时可以离开网络(出口)以及流向哪里同样至关重要。在这篇文章中,我们将不深入讨论为什么控制出口流量如此重要的理论细节,毕竟,前人已经说的口都干了。因此,本文仅从技术演进层面来探讨关于在云原生生态中“出口”的选型及实现场景。
94 0
|
10月前
|
存储 人工智能 Kubernetes
Kubernetes-k8s
Kubernetes(通常简称为"k8s")是一种开源容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它最初由Google开发,并于2014年发布为开源项目,目前由云原生计算基金会(CNCF)管理和维护。
96 1
|
存储 Kubernetes 监控
kubernetes 安全
kubernetes 安全
|
Kubernetes 监控 安全
1. 认识kubernetes
1. 认识kubernetes
|
存储 Kubernetes 监控
Kubernetes 60 个为什么
Kubernetes 60 个为什么
147 0