前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >k8s实践(3)--k8s集群安装详解

k8s实践(3)--k8s集群安装详解

作者头像
黄规速
发布2022-04-14 16:13:39
8.5K1
发布2022-04-14 16:13:39
举报
文章被收录于专栏:架构师成长之路

k8s实践系列的相关配置都在github:https://github.com/huangguisu/k8s.git

一、部署架构规划和环境准备

1、安装方式选择

目前有三种安装方式

第一种是yum安装

使用yum安装,好处是简单,缺点就是要获取最新版需要跟你学yum源,而且所有软件的依赖又不能自己指定,尤其是系统版本比较,使用yum源安装的kubernetes的版本也会受到限制。

第一种是二进制安装

使用二进制文件安装,好处是可以安装任意版本的kubernetes,坏处是配置比较复杂。虽然二进制安装包安装的方式比较费劲,但是二进制便于熟悉各个组件,对学习k8s是很有好处的,因此我们的教程里面全都是二进制安装。

第三种是kubeadm安装

kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,将k8s的各个组件都安装在docker之上,以容器的方式运行。伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践。

2、下载版本

https://github.com/kubernetes/kubernetes/releases

从上边的网址中选择相应的版本,从 CHANGELOG页面 下载二进制文件,本文以1.14.1版本为例

https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md#v1142

选择Service Binaries中的kubernetes-server-linux-amd64.tar.gz

该文件已经包含了 K8S所需要的全部组件,无需单独下载Client等组件。

解压后,在kubernetes/server/bin 路径下包含一些必须的组件:

设置环境变量方便直接使用kubernetes的命令:

export K8S_BIN=/mnt/app/kubernetes/server/bin/ export PATH="

3、节点规划和环境准备

k8s至少需要一个master和一个node才能组成一个可用集群。我们将搭建一个master节点和2个node节点。

我们有三台服务器,规划如下,最好然后修改hosts

192.168.10.21 k8s-master

192.168.10.22 k8s-node1

192.168.10.23 k8s-node2

1、修改 /etc/hosts 文件,添加域名解析,方便后续使用

代码语言:javascript
复制
cat <<EOF >>/etc/hosts
192.168.10.21  k8s-master
192.168.10.22  k8s-node1
192.168.10.23  k8s-node1
192.168.10.21 node1.etcd.k8-cluster.com
192.168.10.22 node2.etcd.k8-cluster.com
192.168.10.23 node3.etcd.k8-cluster.com
EOF

2.关闭防火墙、selinux和swap。

代码语言:javascript
复制
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
#关闭swap
swapoff -a
#要永久禁掉swap分区,/etc/fstab文件注释掉swap那一行
sed -i 's/.*swap.*/#&/' /etc/fstab

4、准备证书:

具体说明:k8s实践(8)--ssl安全认证配置

相关证书放在:/mnt/app/kubernetes/ssl/

mkdir /mnt/app/kubernetes/ssl/

cat <<EOF >> /mnt/app/kubernetes/ssl/masterssl.cnf

req

req_extensions = v3_req

distinguished_name = req_distinguished_name

req_distinguished_name

v3_req

basicConstraints = CA:FALSE

keyUsage = nonRepudiation, digitalSignature, keyEncipherment

subjectAltName = @alt_names

alt_names

DNS.1 = kubernetes

DNS.2 = kubernetes.default

DNS.3 = kubernetes.default.svc

DNS.4 = kubernetes.default.svc.cluster.local

DNS.5 = master.k8s.tulingapi.com

DNS.6 = k8s-master

IP.4 = 127.0.0.1

IP.1 = 192.168.10.21

IP.2 = 192.168.0.1

IP.3 = 10.0.0.1

IP.4 = 172.17.0.1

IP.4 = 172.16.0.1

IP.4 = 172.18.0.1

EOF

#根证书

openssl genrsa -out ca-private.pem 2048

openssl req -x509 -new -nodes -key ca-private.pem -days 3650 -out ca-public.pem -subj "/CN=kube-ca"

#apiserver证书

openssl genrsa -out apiserver-private.pem 2048

openssl req -new -key apiserver-private.pem -out apiserver.csr -subj "/CN=k8s-master" -config masterssl.cnf

openssl x509 -req -in apiserver.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out apiserver-public.pem -days 3650 -extensions v3_req -extfile masterssl.cnf

#设置kube-controller-manager的客户端证书

openssl genrsa -out manager-client-private.pem 2048

openssl req -new -key manager-client-private.pem -subj "/CN=k8s-master" -out manager-client.csr

openssl x509 -req -in manager-client.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out manager-client-public.pem -days 5000

#node节点客户端双向证书生成

openssl genrsa -out kubelet-private.pem 2048

openssl req -new -key kubelet-private.pem -out kubelet.csr -subj "/CN=kubelet-key"

openssl x509 -req -in kubelet.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out kubelet-public.pem -days 3650

二、高可用Kubernetes Master节点安装

kubernetes master 节点包含的组件。

  • kube-apiserver
  • kube-scheduler
  • kube-controller-manager

kube-schedulerkube-controller-managerkube-apiserver 三者的功能紧密相关,因此建议这三个组件部署在同一台机器上。同时只能有一个 kube-schedulerkube-controller-manager 进程处于工作状态,如果运行多个,则需要通过选举产生一个 leader;

Kubernetes 的服务都是通过直接运行二进制文件加启动参数完成,为了便于管理,常见的做法:

1、可以使用nohup运行二进制文件来实现后台运行。

2、将Kubernetes服务进程配置成系统服。

3、使用supervisor来管理,我们这里都使用这个方式。

2.1、Kuber-apiserver

2.1.1 Kubernetes API Server概述

Kubernetes API Server的核心功能是提供了Kubernetes各类资源对象(如Pod、RC、Service等)的增、删、改、查及Watch等HTTP Rest接口,成为集群内各个功能模块之间数据交互和通信的中心枢纽,是整个系统的数据总线和数据中心。除此之外,他还有以下的特性:

  1. 是集群管理的API入口;
  2. 是资源配额控制的入口;
  3. 提供完备的集群安全机制;

2.1.2 启动Kube-apiserver 进程服务

Kubernetes API Server通过一个名为Kube-apiserver的进程提供服务,该进程运行在Master节点上。在默认情况下,kube-apiserver进程在本机的8080端口(对应参数--insecure-port)提供REST服务。

简单使用nohup启动,由于我本地端口8080被占用,修改kube-apiserver端口为9090

nohup /mnt/app/kubernetes/server/bin/kube-apiserver --insecure-bind-address=0.0.0.0 --insecure-port=9090 --etcd-servers=http://node1.etcd.k8-cluster.com:2379 --service-cluster-ip-range=192.168.10.0/16 --admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/mnt/logs/k8s-kube-apiserver/ --v=2 &

kubectl命令默认连接的server 是http://localhost:8080,由于改了端口号需指定server,可以通过alias 来修改: alias kubectl=" kubectl -s http://localhost:9090" echo alias kubectl=" kubectl -s http://localhost:9090" >> ~/.bashrc

我们可以同时启动HTTPS安全端口(--secure-port=6443)来启动安全机制,加强REST API访问的安全性。

如果集群要可以发布pod,必须的使用ssl认证启动:

nohup /mnt/app/kubernetes/server/bin/kube-apiserver --insecure-bind-address=0.0.0.0 --insecure-port=9090 --etcd-servers=http://node1.etcd.k8-cluster.com:2379 --service-cluster-ip-range=192.168.10.0/16 --service-account-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem --client-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem --tls-private-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem --tls-cert-file=/mnt/app/kubernetes/ssl/apiserver-public.pem --admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/mnt/logs/k8s-kube-apiserver/ --v=2 &

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kube-apiserver.conf

2.1.3 配置参数说明:

通用参数: –admission-control=”AlwaysAdmit”:集群中资源的Admission Controller的插件的有序列表,分别使用逗号分隔,AlwaysAdmit, –admission-control-config-file=””: Admission Controller配置文件。 –advertise-address=<nil>: 广播API Server给所有集群成员的IP地址。其它集群都可以访问该IP地址,如果为空,会使用—-allow-privileged=false: true,表示允许特权容器。 –authorization-mode=”AlwaysAllow”: 安全端口授权插件的有序列表,分别以逗号分隔,AlwaysAllow,AlwaysDeny,ABAC–authorization-policy-file=””: 授权策略的CSV文件,使用于–authorization-mode=ABAC模式的配置。 –basic-auth-file=””: 如果配置该选项,该文件会通过HTTP基本认证允许API Server安全端口的请求。 –bind-address=0.0.0.0: 服务–read-only-port和–secure-port端口的IP地址。相关接口必须是其它集群通过CLI/web客–cert-dir=”/var/run/kubernetes”: TLS证书的目录(默认/var/run/kubernetes)。如果配置–tls-cert-file和–tls—client-ca-file=””: 如果设置,任何提交客户端证书的请求都会验证与相关客户端证书的CommonName的身份。该客户端证书是–cloud-config=””: 云提供商配置文件的路径,空表示没有该配置文件。 –cloud-provider=””: 云服务的提供商,空表示没有该提供商。 –cluster-name=”kubernetes”: 集群实例的前缀。 –cors-allowed-origins=[]: CORS的允许起源(allowed origins, 翻译待考虑)的列表,用逗号分隔。一个允许起源可以是 ETCD参数: –etcd-config=””: ETCD客户端的配置文件,与-etcd-servers配置项互斥。 –etcd-prefix=”/registry”: ETCD中所有资源路径的前缀。 –etcd-servers=[]: ETCD服务器(http://ip:port)列表,以逗号分隔。与-etcd-config配置项互斥。 –etcd-servers-overrides=[]: 每个资源ETCD服务器覆盖文件,以逗号分隔。独立覆盖格式,group/resource#servers,服 其他参数; –event-ttl=1h0m0s: 保留事件的时间值,默认1小时。 –experimental-keystone-url=””: 如果Passed,激活Keystone认证插件。 –external-hostname=””: 为Master生成外部URLs使用的主机名。 –google-json-key=””: 用户Google Cloud Platform Service Account JSON Key认证。 –insecure-bind-address=127.0.0.1:非安全端口(所有接口都设置为0.0.0.0)的服务IP地址。默认是本地地址。 –insecure-port=8080: 不安全且没有认证的进程访问端口,默认8080。假设防火墙规则设置该端口从集群外部禁止访问,并且在–kubelet-certificate-authority=””: 证书路径。证书授权文件。 –kubelet-client-certificate=””: TLS客户端证书文件路径。 –kubelet-client-key=””: TLS客户端秘钥文件路径。 –kubelet-https=true: 使用https建立Kubelet连接。 –kubelet-port=10250: Kubelet端口。 –kubelet-timeout=5s: Kubelet操作Timeout值。 –log-flush-frequency=5s: 日志缓冲秒数的最大值。 –long-running-request-regexp=”(/|^)((watch|proxy)(/|)|(logs?|portforward|exec|attach)/? )”: 匹配长–master-service-namespace=”default”: Namespace,该Namespace的Kubernetes主服务应该注入Pod。 –max-connection-bytes-per-sec=0: 如果非零,表示每个用户连接的最大值,字节数/秒,当前只适用于长时间运行的请求。 –max-requests-inflight=400: 给定时间内运行的请求的最大值。如果超过最大值,该请求就会被拒绝。零表示没有限制。 –min-request-timeout=1800: 这是个可选字段,表示一个请求处理的最短时间,单位是秒。在超时之前,这个请求必须是激活的–oidc-ca-file=””: 如果设置该选项,Oidc-ca-file中的相关机构会验证OpenID服务的证书。否则,会使用主机的根证书。 –oidc-client-id=””: 如果设置了oidc-issuer-url字段,该字段,OpenID连接客户端的客户ID也必须设置。 –oidc-issuer-url=””: OpenID发行的URL,只接受HTTPS协议。如果设置该字段,将被用来验证OIDC JSON Web Token(JWT)–oidc-username-claim=”sub”: 。默认值之外的那些值,可能是不唯一的,可变的。这个标志还在尝试中,详情请参考Authentication –profiling=true: 通过web接口进行分析 host:port/debug/pprof/。 –runtime-config=: key=value键值对集,描述运行时配置,也会回传输到apiserver。apis/键值用于打开–secure-port=6443: 用于HTTPS的认证和授权。0表示不支持HTTPS服务。 –service-account-key-file=””: 该文件包含RPM-encoded x509 RSA的私钥和公钥,用于验证ServiceAccount的Token。–service-account-lookup=false: true, 表示验证Service Account的Token做为Authentication一部分在ETCD中的 –service-cluster-ip-range=: CIDR标记的IP范围,从中分配IP给服务集群。该范围不能与分配给Pod节点的任何IP范围–service-node-port-range=: NodePort可见性服务的端口范围,包含范围的两端。如’30000-32767’,包含30000和32767–ssh-keyfile=””: 如果非空,使用安全SSH代理到该节点,用该秘钥文件。 –ssh-user=””: 如果非空,使用安全SSH代理到该节点,用该用户名。 –storage-versions=”extensions/v1beta1,v1″: 存储资源的版本。不同的组存储在不同的版本里面,指定格式”group1/version1,–tls-cert-file=””: 该文件包含HTTPS的x509证书。(CA证书,如果存在,连接在服务器证书之后)。如果支持HTTPS服务,且没–tls-private-key-file=””: 该文件包含x509私钥匹配项–tls-cert-file. –token-auth-file=””: 该文件使用Token验证保护API Server的安全端口。 –watch-cache=true: 可以在API Server查看缓存。

2.1.4 Kubernetes API Server使用

通常我们可以通过命令行工具kubectl来与kubernetes API Server交互,他们之间的接口是REST调用。也可以使用curl命令行工具进行快速测试验证。

查看Kubernetes API的版本信息

curl k8s-master:9090/api

查看Kubernetes API Server目前支持的资源对象的种类

curl k8s-master:9090/api/v1

查看不同资源列表信息:

curl k8s-master:9090/api/v1/pods

curl k8s-master:9090/api/v1/services

curl k8s-master:9090/api/v1/replicationcontrollers

2.1.5 Kubernetes-Proxy API管理Node接口

这类接口的作用是代理REST请求,即kubernetes API Server把收到的REST请求转发到某个Node上的kubelet守护进程的REST端口上,由该kubelet进程负责响应。

Kubernetes Proxy API中管理Node的相关接口,该接口的REST路径为/api/v1/proxy/nodes/{name},其中name为节点名称或IP地址,包括以下几个具体的接口:

  • /api/v1/proxy/nodes/{name}/pods  #列出指定节点内的所有Pod的信息
  • /api/v1/proxy/nodes/{name}/stats #列出指定节点内物理资源的统计信息
  • /api/v1/proxy/nodes/{name}/spec #列出指定节点的概要信息

例:节点名为k8s-node-1,下面命令获取该节点上所有运行中的pod:

  • curl localhost:8080/api/v1/proxy/nodes/k8s-node-1/pods

需要说明的是,此处获取pod信息数据来自Node而非etcd数据库,所以两者可能在某些时间点会有偏差。此外如果kubelet进程在启东时包含--enable-debugging-handles=true,namekubernetes Proxy API 还会增加下面的接口:

  • /api/v1/proxy/nodes/{name}/run #在节点上运行某个容器
  • /api/v1/proxy/nodes/{name}/exec #在节点的某个容器中运行某条命令
  • /api/v1/proxy/nodes/{name}/attach #在节点上attach某个容器
  • /api/v1/proxy/nodes/{name}/portForward #实现节点上的Pod端口转发
  • /api/v1/proxy/nodes/{name}/logs #列出节点的各类日志信息,例如tallylog、lastlog、wtmp、ppp/、rhsm、audit、tuned、和anaconda等
  • /api/v1/proxy/nodes/{name}/metrics #列出和该节点相关的Metrics信息
  • /api/v1/proxy/nodes/{name}/runningpods #列出节点内运行中的Pod信息
  • /api/v1/proxy/nodes/{name}/debug/pprof #列出节点内当前Web服务的状态,包括CPU和内存的使用情况

Kubernetes Proxy API里关于Pod的相关接口,通过这些接口,我们可以访问pod里某个容器提供的服务(如Tomcat在8080提供的服务)

  • /api/v1/proxy/namespaces/{namespace}/pods/{name}/{patch:*} #访问pod的某个服务接口
  • /api/v1/proxy/namespaces/{namespace}/pods/{name} #访问pod
  • /api/v1/proxy/namespaces/{namespace}/pods/{name}/proxy/{patch:*} #访问pod的某个服务接口
  • /api/v1/proxy/namespaces/{namespace}/pods/{name}/proxy #访问pod

在上面的4个接口中,后面两个接口的功能和前面两个完全一样,只是写法不同。

2.1.6 kube-proxy 代理接口

如果我们只想对外暴露部分REST服务,则可以在Master或其他任何节点上通过运行kube-proxy进程启动一个内部代理来实现。

运行下面的命令,我们在8001端口启动代理,并且拒绝客户端访问RC的API:

  • kubectl proxy --reject-paths=“^/api/v1/replicationcontrollers” --port=8001 --v=2

通过下面的命令进行验证:

  • curl localhost:8001/api/v1/replicationcontrollers

kubectl proxy具有很多特性,最实用的一个特性是提供简单有效的安全机制,比如采用白名单来限制非法客户端访问时,只要采用下面的参数即可:

  • --accept-host=“^localhost,^127\\.0\\.0\\.1 ,^\::1\

最后一种方式是通过b编程的方式调用Kubernetes API Server。具体使用场景又细分为以下两种:

第一种使用场景:运行在Pod中的用户进程调用Kubernetes API,通常用来实现分布式集群搭建的目标。Pod中的进程如何知道API Server的访问地址呢,因为Kubernetes API Server本身也是一个Service,其名字就是Kubernetes,他的clusterIP地址是ClusterIP地址池中的第一个IP,他所服务的端口是HTTPS端口443,通过kubectl get svc可以确认这一点。

第二种使用场景:开发基于Kubernetes的管理平台。比如调用Kubernetes API 来完成Pod、Service、RC等资源对象的图形化创建和管理界面,此时可以使用kubernetes及各开源社区为开发人员提供的各种语言版本的Client Library。

2.1.7 集群功能模块之间的通信

集群内各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据时,则通过API Server提供的REST接口(用GET/LIST/WTCH方法)来实现,从而实现各模之间的信息交互;

kubelet进程与API Server的交互:每个node上的kubelet每隔一个时间周期,就会调用一次API Server的REST接口报告自身状态,API Server接收到这些信息后,将各节点信息更新到etcd中。

代码语言:txt
复制
   此外kubelet也通过API Server的watch接口监听pod信息,如果监听到新的Pod副本被调度绑定到本节点,则执行Pod对应的容器的创建和启动逻辑;如果监听到Pod对象被删除,则删除本节点上的相应的Pod容器;如果监听到修改Pod信息,则kubelet监听到变化后,会相应的修改本节点的Pod容器。

kube-controller-manager进程与API Server的交互:kube-controller-manager中的Node Controller模块通过API Server提供的Watch接口,实时监控Node的信息并做相应的处理;

kube-scheduler与API Server交互:当scheduler通过API Server的Watch接口监听到新建Pod副本的信息后,他会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑,调度成功后将Pod绑定到目标节点上。为了缓解集群各模块对API Server的压力,各功能模块都采用缓存的机制来缓存数据。各功能模块定时从API Server获取指定资源对象的信息(通过LIST或watch),然后将这些信息保存到本地缓存,功能模块在某些情况下不直接访问API Server,而是通过访问缓存数据来间接访问API Server

2.2、Kuber-controller-manager

Kube-controller-manager处理集群中常规后台任务, 如果APIServer做的是前台的工作的话,那么controller manager就是负责后台的。每一个资源都对应一个控制器。而control manager就是负责管理这些控制器的,负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;比如我们通过APIServer创建了一个Pod,当这个Pod创建成功后,APIServer的任务就算完成了。

启动Kube-controller-manager, 依赖kube-apiserver(--master=http://k8s-master:9090 ):

nohup kube-controller-manager --master=http://k8s-master:9090 --logtostderr=false --log-dir=/mnt/logs/k8s-kube-controller-manager/ --v=2 &

Kube-controller-manager主要的配置参数:

--master: 指定apiserver的URL地址

--logtostderr=false: 设置为false表示将日志写入文件,不写入则为stderr

--log-dir=/mnt/logs/k8s/ :日志目录

--v=2 :日志等级

上面这个启动命令比较简单,由于发布pod等相关资源需要安全验证,因此需要使用https。

关于Kubernetes安全: https://guisu.blog.csdn.net/article/details/95067232 和ssl证书:https://cloud.tencent.com/developer/article/1981384

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kube-controller-manager.conf

supervisor启动是最终集群版的结果:

代码语言:javascript
复制
[program:k8s-kube-controller-manager]
[program:k8s-kube-controller-manager]
command =/mnt/app/kubernetes/server/bin/kube-controller-manager --master=https://k8s-master:6443 --cluster-cidr=10.0.0.0/16 --service-account-private-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem  --root-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem  --cluster-signing-cert-file=/mnt/app/kubernetes/ssl/ca-public.pem  --cluster-signing-key-file=/mnt/app/kubernetes/ssl/ca-private.pem --kubeconfig=/mnt/app/kubernetes/ssl/kubeconfig.yaml   --logtostderr=false --log-dir=/mnt/logs/k8s-kube-controller-manager/  --v=2
process_name=%(program_name)s
numprocs=1
directory=/mnt/app/kubernetes/
user=root
stdout_logfile=/mnt/logs/%(program_name)s/server.log
stderr_logfile=/mnt/logs/%(program_name)s/error.log
serverurl=AUTO = /mnt/logs/k8s-kube-apiserver/error.log

2.3、Kuber-scheduler

schedule按照预定的调度策略将Pod调度到相应的Node节点上. 如果把scheduler看成一个黑匣子,那么它的输入是pod和由多个Node组成的列表,输出是Pod和一个Node的绑定。 kubernetes目前提供了调度算法,同样也保留了接口。用户根据自己的需求定义自己的调度算法。

启动 kube-scheduler, 依赖kube-apiserver(--master=http://k8s-master:9090 ):

nohup kube-scheduler --master=http://k8s-master:9090 --logtostderr=false --log-dir=/mnt/logs/k8s-kube-scheduler/ --v=2 &

验证Master是否安装成功

$ kubectl get componentstatuses

使用supervisor管理:

代码语言:javascript
复制
[program:k8s-kube-scheduler]
command =/mnt/app/kubernetes/server/bin/kube-scheduler --master=http://k8s-master:9090 --address=0.0.0.0  --logtostderr=false --log-dir=/mnt/logs/k8s-kube-scheduler/  --v=2
process_name=%(program_name)s
numprocs=1
directory=/mnt/app/kubernetes/
umask=022
priority=999
autostart=true
autorestart=true
startsecs=10
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
user=root
redirect_stderr=true
stdout_logfile=/mnt/logs/%(program_name)s/server.log
stdout_logfile_maxbytes=50000MB
stdout_logfile_backups=10
stdout_capture_maxbytes=0MB
stdout_events_enabled=false
stderr_logfile=/mnt/logs/%(program_name)s/error.log
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_capture_maxbytes=1MB
stderr_events_enabled=false
;environment=JAVA_HOME="/usr/java"
serverurl=AUTO = /mnt/logs/k8s-kube-apiserver/error.log

三、Node节点

每个Node节点主要由四个模板组成:kublet, kube-proxy,docker,flanneld

kube-scheduler 也依赖kube-apiserver

在工作node节点上,先安装好docker,并且启动docker deamon.

将kubernetes-server-linux-amd64.tar.gz复制所有的node节点服务器上解压到:/mnt/app/kubernetes/

设置环境变量:

export K8S_BIN=/mnt/app/kubernetes/server/bin/ export PATH="

1 kubeket服务

kublet是Master在每个Node节点上面的agent,是Node节点上面最重要的模块,它负责维护和管理该Node上的所有容器,但是如果容器不是通过kubernetes创建的,它并不会管理。本质上,它负责使Pod的运行状态与期望的状态一致。

kublet 运行在每个 worker 节点上,接收 kube-apiserver 发送的请求,管理 Pod 容器,执行交互式命令,如exec、run、logs 等;

kublet 启动时自动向 kube-apiserver 注册节点信息,内置的 cadvisor 统计和监控节点的资源使用情况;

为确保安全,本文档只开启接收 https 请求的安全端口,对请求进行认证和授权,拒绝未授权的访问(如apiserver、heapster)。

而官方推荐我们使用--config指定配置文件,并在配置文件中指定原来这些flag所配置的内容。具体内容可以查看这里Set Kubelet parameters via a config file。这也是Kubernetes为了支持动态Kubelet配置(Dynamic Kubelet Configuration)才这么做的,参考Reconfigure a Node’s Kubelet in a Live Cluster

kubelet的配置文件必须是json或yaml格式,具体可查看这里

Kubernetes 1.8开始要求关闭系统的Swap,如果不关闭,默认配置下kubelet将无法启动。 关闭系统的Swap方法如下:

swapoff -a

修改 /etc/fstab 文件,注释掉 SWAP 的自动挂载,使用free -m确认swap已经关闭。 swappiness参数调整,修改/etc/sysctl.d/k8s.conf添加下面一行:

vm.swappiness=0

在从Kubernetes 1.10开始Dynamic Kubelet Configuration特性进入beta阶段,kubelet的大多数命令行参数都改为推荐在--config指定位置的配置文件中进行配置,包括---cluster-dns--cluster-domain两个参数.

因为1.9.0在kubelet里不再使用KUBELET_API_SERVER来跟API通信,而是通过别一个yaml的配置来实现。

nohup kubelet --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kube-scheduler/ --v=2 &

使用这个:

nohup kubelet --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kubelet/ --v=2 --cgroup-driver=systemd --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice &

/mnt/app/kubernetes/conf/kubelet.yaml:

代码语言:javascript
复制
chown -R kubelet.kubelet /mnt/app/kubernetes/conf/kubelet.yaml

apiVersion: v1 kind: Config users:name: kubelet cgroupDriver: systemd clusters: name: kubernetes cluster: server: http://k8s-master:8080 contexts: context: cluster: kubernetes user: kubelet name: service-account-context current-context: service-account-contex

cgroupDriver 默认是cgroupfs

  • Kubelet Node Allocatable用来为Kube组件和System进程预留资源,从而保证当节点出现满负荷时也能保证Kube和System进程有足够的资源。
  • 目前支持cpu, memory, ephemeral-storage三种资源预留。
  • Node Capacity是Node的所有硬件资源,kube-reserved是给kube组件预留的资源,system-reserved是给System进程预留的资源, eviction-threshold是kubelet eviction的阈值设定,allocatable才是真正scheduler调度Pod时的参考值(保证Node上所有Pods的request resource不超过Allocatable)。
  • Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold

--enforce-node-allocatable,默认为pods,要为kube组件和System进程预留资源,则需要设置为pods,kube-reserved,system-reserve。 --cgroups-per-qos,Enabling QoS and Pod level cgroups,默认开启。开启后,kubelet会将管理所有workload Pods的cgroups。 --cgroup-driver,默认为cgroupfs,另一可选项为systemd。取决于容器运行时使用的cgroup driver,kubelet与其保持一致。比如你配置docker使用systemd cgroup driver,那么kubelet也需要配置--cgroup-driver=systemd。 --kube-reserved,用于配置为kube组件(kubelet,kube-proxy,dockerd等)预留的资源量,比如—kube-reserved=cpu=1000m,memory=8Gi,ephemeral-storage=16Gi。 --kube-reserved-cgroup,如果你设置了--kube-reserved,那么请一定要设置对应的cgroup,并且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为kube-reserved-cgroup=/kubelet.service 。 --system-reserved,用于配置为System进程预留的资源量,比如—system-reserved=cpu=500m,memory=4Gi,ephemeral-storage=4Gi。 --system-reserved-cgroup,如果你设置了--system-reserved,那么请一定要设置对应的cgroup,并且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为system-reserved-cgroup=/system.slice。 --eviction-hard,用来配置kubelet的hard eviction条件,只支持memory和ephemeral-storage两种不可压缩资源。当出现MemoryPressure时,Scheduler不会调度新的Best-Effort QoS Pods到此节点。当出现DiskPressure时,Scheduler不会调度任何新Pods到此节点。关于Kubelet Eviction的更多解读,请参考我的相关博文。 Kubelet Node Allocatable的代码很简单,主要在pkg/kubelet/cm/node_container_manager.go,感兴趣的同学自己去走读一遍。 –hostname-override 指定 hostname,如果非空会使用这个值作为节点在集群中的标识

然后检查节点是否成功加入集群:

kubectl get cs,nodes

如果修改了apiserver端口:

kubectl -s http://localhost:9090 get cs,nodes

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kubelet.conf

2 kube-proxy服务

该模块实现了kubernetes中的服务发现和反向代理功能。kube-proxy支持TCP和UDP连接转发,默认基Round Robin算法将客户端流量转发到与service对应的一组后端pod。服务发现方面,kube-proxy使用etcd的watch机制监控集群中service和endpoint对象数据的动态变化,并且维护一个service到endpoint的映射关系,从而保证了后端pod的IP变化不会对访问者造成影响,另外,kube-proxy还支持session affinity。

nohup kube-proxy --master http://k8s-master:8080 --hostname-override=k8s-node1 --logtostderr=false --log-dir=/mnt/logs/k8s-kube-proxy --v=2 &

kubectl -s http://localhost:9090 get nodes

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kube-proxy.conf

问题

1、kubelet启动:

看到最后一行:error: failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd"

kubelet的cgroup-driver与docker设置的不一致导致无法启动

这个好特么坑,docker是使用cgroup技术来限制容器的资源的。 docker的启动参数中特意有一个参数是--cgroup-driver

kubelet文件驱动默认cgroupfs, 而我们安装的docker使用的文件驱动是systemd, 造成不一致, 导致镜像无法启动。

现在有两种方式, 一种是修改docker, 另一种是修改kubelet。

我这里采用修改docker的方式

注意:

修改或创建/etc/docker/daemon.json,加入下面的内容:

{ "exec-opts": ["native.cgroupdriver=systemd"] }

或者修改docker.service

vim /lib/systemd/system/docker.service

将 --exec-opt native.cgroupdriver=systemd 修改为:

--exec-opt native.cgroupdriver=cgroupfs

systemctl daemon-reload

systemctl restart docker.service

kubelet显示正常

修改kubelet的启动参数--cgroup-driver=systemd:

kubelet --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kubelet/ --v=2 --cgroup-driver=systemd

2、kubelet启动报错:

0617 14:25:16.541259 26288 summary.go:102] Failed to get system container stats for "/system.slice/docker.service": failed to get cgroup stats for "/system.slice/docker.service": failed to get container info for "/system.slice/docker.service": unknown container "/system.slice/docker.service"

解决方案,添加启动参数:

--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice

3、 用kubectl logs <podname> -n kube-system查看日志会发现有这样的日志存在

Expected to load root CA config from /var/run/secrets/kubernetes.io/serviceaccount/ca.crt, but got err: open /var/run/secrets/kubernetes.io/serviceaccount/ca.crt: no such file or directory

这是因为kubernetes默认创建的secrets 资源不包含用于访问apiserver的根证书

这需要重新生产证书和秘钥

4、日志报错:k8s-kube-scheduler

Error from server (NotFound): the server could not find the requested resource

或者kubectl get nodes

error: the server doesn't have a resource type "nodes"

错误原因:

默认连接的server 是http://localhost:8080,由于改了端口号需指定server

alias kubectl=" kubectl -s http://localhost:9090"

echo alias kubectl=" kubectl -s http://localhost:9090" >> ~/.bashrc

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/06/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、部署架构规划和环境准备
    • 1、安装方式选择
      • 2、下载版本
        • 3、节点规划和环境准备
          • 4、准备证书:
          • 二、高可用Kubernetes Master节点安装
            • 2.1、Kuber-apiserver
              • 2.1.1 Kubernetes API Server概述
              • 2.1.2 启动Kube-apiserver 进程服务
              • 2.1.3 配置参数说明:
              • 2.1.4 Kubernetes API Server使用
              • 2.1.5 Kubernetes-Proxy API管理Node接口
              • 2.1.6 kube-proxy 代理接口
              • 2.1.7 集群功能模块之间的通信
            • 2.2、Kuber-controller-manager
              • 2.3、Kuber-scheduler
              • 三、Node节点
                • 1 kubeket服务
                  • 2 kube-proxy服务
                  • 问题
                  • 看到最后一行:error: failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd"
                  • vim /lib/systemd/system/docker.service
                  • 将 --exec-opt native.cgroupdriver=systemd 修改为:
                  • --exec-opt native.cgroupdriver=cgroupfs
                  • systemctl daemon-reload
                  • systemctl restart docker.service
                  • kubelet显示正常
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档