k8s实践系列的相关配置都在github:https://github.com/huangguisu/k8s.git
目前有三种安装方式
第一种是yum安装
使用yum安装,好处是简单,缺点就是要获取最新版需要跟你学yum源,而且所有软件的依赖又不能自己指定,尤其是系统版本比较,使用yum源安装的kubernetes的版本也会受到限制。
第一种是二进制安装
使用二进制文件安装,好处是可以安装任意版本的kubernetes,坏处是配置比较复杂。虽然二进制安装包安装的方式比较费劲,但是二进制便于熟悉各个组件,对学习k8s是很有好处的,因此我们的教程里面全都是二进制安装。
第三种是kubeadm安装
kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,将k8s的各个组件都安装在docker之上,以容器的方式运行。伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践。
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="$K8S_BIN:$PATH"
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 文件,添加域名解析,方便后续使用
cat <>/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。
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
kubernetes master 节点包含的组件。
kube-scheduler
、kube-controller-manager
和 kube-apiserver
三者的功能紧密相关,因此建议这三个组件部署在同一台机器上。同时只能有一个 kube-scheduler
、kube-controller-manager
进程处于工作状态,如果运行多个,则需要通过选举产生一个 leader;
Kubernetes 的服务都是通过直接运行二进制文件加启动参数完成,为了便于管理,常见的做法:
1、可以使用nohup运行二进制文件来实现后台运行。
2、将Kubernetes服务进程配置成系统服。
3、使用supervisor来管理,我们这里都使用这个方式。
Kubernetes API Server的核心功能是提供了Kubernetes各类资源对象(如Pod、RC、Service等)的增、删、改、查及Watch等HTTP Rest接口,成为集群内各个功能模块之间数据交互和通信的中心枢纽,是整个系统的数据总线和数据中心。除此之外,他还有以下的特性:
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
通用参数:
–admission-control=”AlwaysAdmit”:集群中资源的Admission Controller的插件的有序列表,分别使用逗号分隔,AlwaysAdmit,
–admission-control-config-file=””: Admission Controller配置文件。
–advertise-address=: 广播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查看缓存。
通常我们可以通过命令行工具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
这类接口的作用是代理REST请求,即kubernetes API Server把收到的REST请求转发到某个Node上的kubelet守护进程的REST端口上,由该kubelet进程负责响应。
Kubernetes Proxy API中管理Node的相关接口,该接口的REST路径为/api/v1/proxy/nodes/{name},其中name为节点名称或IP地址,包括以下几个具体的接口:
例:节点名为k8s-node-1,下面命令获取该节点上所有运行中的pod:
需要说明的是,此处获取pod信息数据来自Node而非etcd数据库,所以两者可能在某些时间点会有偏差。此外如果kubelet进程在启东时包含--enable-debugging-handles=true,namekubernetes Proxy API 还会增加下面的接口:
Kubernetes Proxy API里关于Pod的相关接口,通过这些接口,我们可以访问pod里某个容器提供的服务(如Tomcat在8080提供的服务)
在上面的4个接口中,后面两个接口的功能和前面两个完全一样,只是写法不同。
如果我们只想对外暴露部分REST服务,则可以在Master或其他任何节点上通过运行kube-proxy进程启动一个内部代理来实现。
运行下面的命令,我们在8001端口启动代理,并且拒绝客户端访问RC的API:
通过下面的命令进行验证:
kubectl proxy具有很多特性,最实用的一个特性是提供简单有效的安全机制,比如采用白名单来限制非法客户端访问时,只要采用下面的参数即可:
最后一种方式是通过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。
集群内各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据时,则通过API Server提供的REST接口(用GET/LIST/WTCH方法)来实现,从而实现各模之间的信息交互;
kubelet进程与API Server的交互:每个node上的kubelet每隔一个时间周期,就会调用一次API Server的REST接口报告自身状态,API Server接收到这些信息后,将各节点信息更新到etcd中。
此外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
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://guisu.blog.csdn.net/article/details/95459273
使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kube-controller-manager.conf
supervisor启动是最终集群版的结果:
[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
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管理:
[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节点主要由四个模板组成: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="$K8S_BIN:$PATH"
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:
chown -R kubelet.kubelet /mnt/app/kubernetes/conf/kubelet.yaml
apiVersion: v1
kind: Config
users:
- name: kubeletcgroupDriver: 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
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
该模块实现了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
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