K8S基础概念
一、核心概念
1、Node
Node作为集群中的工作节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod。Node上运行着Kubernetes的Kubelet、kube-proxy服务进程,这些服务进程负责Pod的创建、启动、监控、重启、销毁、以及实现软件模式的负载均衡。
Node包含的信息:
· Node地址:主机的IP地址,或Node ID。
· Node的运行状态:Pending、Running、Terminated三种状态。
· Node Condition:…
· Node系统容量:描述Node可用的系统资源,包括CPU、内存、最大可调度Pod数量等。
· 其他:内核版本号、Kubernetes版本等。
查看Node信息:
kubectl describe node
2、Pod
Pod是Kubernetes最基本的操作单元,包含一个或多个紧密相关的容器,一个Pod可以被一个容器化的环境看作应用层的“逻辑宿主机”;一个Pod中的多个容器应用通常是紧密耦合的,Pod在Node上被创建、启动或者销毁;每个Pod里运行着一个特殊的被称之为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume挂载卷,因此他们之间通信和数据交换更为高效,在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个Pod中。
同一个Pod里的容器之间仅需通过localhost就能互相通信。
一个Pod中的应用容器共享同一组资源:
· PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID;
· 网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围;
· IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信;
· UTS命名空间:Pod中的多个容器共享一个主机名;
· Volumes(共享存储卷):Pod中的各个容器可以访问在Pod级别定义的Volumes;
Pod的生命周期通过Replication Controller来管理;通过模板进行定义,然后分配到一个Node上运行,在Pod所包含容器运行结束后,Pod结束。
Kubernetes为Pod设计了一套独特的网络配置,包括:为每个Pod分配一个IP地址,使用Pod名作为容器间通信的主机名等。
3、Service
在Kubernetes的世界里,虽然每个Pod都会被分配一个单独的IP地址,但这个IP地址会随着Pod的销毁而消失,这就引出一个问题:如果有一组Pod组成一个集群来提供服务,那么如何来访问它呢?Service!
一个Service可以看作一组提供相同服务的Pod的对外访问接口,Service作用于哪些Pod是通过Label Selector来定义的。
· 拥有一个指定的名字(比如my-mysql-server);
· 拥有一个虚拟IP(ClusterIP、ServiceIP或VIP)和端口号,销毁之前不会改变,只能内网访问;
· 能够提供某种远程服务能力;
· 被映射到了提供这种服务能力的一组容器应用上;
如果Service要提供外网服务,需指定公共IP和NodePort,或外部负载均衡器;
NodePort
系统会在Kubernetes集群中的每个Node上打开一个主机的真实端口,这样,能够访问Node的客户端就能通过这个端口访问到内部的Service了
4、Volume
Volume是Pod中能够被多个容器访问的共享目录。
5、Label
Label以key/value的形式附加到各种对象上,如Pod、Service、RC、Node等,以识别这些对象,管理关联关系等,如Service和Pod的关联关系。
6、RC(ReplicationController)
· 目标Pod的定义;
· 目标Pod需要运行的副本数量;
· 要监控的目标Pod标签(Lable);
Kubernetes通过RC中定义的Lable筛选出对应的Pod实例,并实时监控其状态和数量,如果实例数量少于定义的副本数量(Replicas),则会根据RC中定义的Pod模板来创建一个新的Pod,然后将此Pod调度到合适的Node上启动运行,直到Pod实例数量达到预定目标。
二、Kubernetes总体架构
Master和Node
Kubernetes将集群中的机器划分为一个Master节点和一群工作节点(Node)。其中,Master节点上运行着集群管理相关的一组进程etcd、API Server、Controller Manager、Scheduler,后三个组件构成了Kubernetes的总控中心,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理功能,并且全都是自动完成。在每个Node上运行Kubelet、Proxy、Docker daemon三个组件,负责对本节点上的Pod的生命周期进行管理,以及实现服务代理的功能。
流程
通过Kubectl提交一个创建RC的请求,该请求通过API Server被写入etcd中,此时Controller Manager通过API Server的监听资源变化的接口监听到这个RC事件,分析之后,发现当前集群中还没有它所对应的Pod实例,于是根据RC里的Pod模板定义生成一个Pod对象,通过API Server写入etcd,接下来,此事件被Scheduler发现,它立即执行一个复杂的调度流程,为这个新Pod选定一个落户的Node,然后通过API Server讲这一结果写入到etcd中,随后,目标Node上运行的Kubelet进程通过API Server监测到这个“新生的”Pod,并按照它的定义,启动该Pod并任劳任怨地负责它的下半生,直到Pod的生命结束。
随后,我们通过Kubectl提交一个新的映射到该Pod的Service的创建请求,Controller Manager会通过Label标签查询到相关联的Pod实例,然后生成Service的Endpoints信息,并通过API Server写入到etcd中,接下来,所有Node上运行的Proxy进程通过API Server查询并监听Service对象与其对应的Endpoints信息,建立一个软件方式的负载均衡器来实现Service访问到后端Pod的流量转发功能。
· etcd
用于持久化存储集群中所有的资源对象,如Node、Service、Pod、RC、Namespace等;API Server提供了操作etcd的封装接口API,这些API基本上都是集群中资源对象的增删改查及监听资源变化的接口。
· API Server
提供了资源对象的唯一操作入口,其他所有组件都必须通过它提供的API来操作资源数据,通过对相关的资源数据“全量查询”+“变化监听”,这些组件可以很“实时”地完成相关的业务功能。
· Controller Manager
集群内部的管理控制中心,其主要目的是实现Kubernetes集群的故障检测和恢复的自动化工作,比如根据RC的定义完成Pod的复制或移除,以确保Pod实例数符合RC副本的定义;根据Service与Pod的管理关系,完成服务的Endpoints对象的创建和更新;其他诸如Node的发现、管理和状态监控、死亡容器所占磁盘空间及本地缓存的镜像文件的清理等工作也是由Controller Manager完成的。
· Scheduler
集群中的调度器,负责Pod在集群节点中的调度分配。
· Kubelet
负责本Node节点上的Pod的创建、修改、监控、删除等全生命周期管理,同时Kubelet定时“上报”本Node的状态信息到API Server里。
· Proxy
实现了Service的代理与软件模式的负载均衡器。
客户端通过Kubectl命令行工具或Kubectl Proxy来访问Kubernetes系统,在Kubernetes集群内部的客户端可以直接使用Kuberctl命令管理集群。Kubectl Proxy是API Server的一个反向代理,在Kubernetes集群外部的客户端可以通过Kubernetes Proxy来访问API Server。
API Server内部有一套完备的安全机制,包括认证、授权和准入控制等相关模块
一、环境介绍及准备:(核心转发一定要开启,所有主机)
1、物理机操作系统
物理机操作系统采用Centos7.364位,细节如下。
[root@localhost ~]# uname -a
Linuxlocalhost.localdomain 3.10.0-514.6.1.el7.x86_64 #1 SMP Wed Jan 18 13:06:36 UTC2017 x86_64 x86_64 x86_64 GNU/Linux
[root@localhost ~]# cat /etc/redhat-release
CentOS Linux release7.3.1611 (Core)
2、主机信息
本文准备了三台机器用于部署k8s的运行环境,细节如下:
节点即功能 主机名 I P
Master。Etcd。registry k8s-master 192.168.8.73
Node1.etcd k8s-node-1 192.168.8.74
Node2.etcd k8s-node-2 192.168.8.72
设置三台机器的主机名:
Master上执行:
[root@localhost ~]# hostnamectl--static set-hostname k8s-master
Node1上执行:
[root@localhost ~]# hostnamectl --static set-hostname k8s-node-1
Node2上执行:
[root@localhost ~]# hostnamectl --static set-hostname k8s-node-2
在三台机器上设置hosts,均执行如下命令:
echo '192.168.8.73 k8s-master
192.168.8.73 etcd
192.168.8.73 registry
192.168.8.74 k8s-node-1
192.168.8.72 k8s-node-2' >>/etc/hosts
3、关闭三台机器上的防火墙
systemctl disable firewalld.service
systemctl stop firewalld.service
二、部署etcd
k8s运行依赖etcd,需要先部署etcd,本文采用yum方式安装:(master和node节点都装etcd)
[root@localhost ~]# yum install etcd -y
yum安装的etcd默认配置文件在/etc/etcd/etcd.conf。编辑配置文件,更改以下带颜色部分信息:(master和node节点区别使用的括号)
[root@localhost ~]# vi /etc/etcd/etcd.conf
# [member]
ETCD_NAME=master (node节点backup)
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
#ETCD_WAL_DIR=""
#ETCD_SNAPSHOT_COUNT="10000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
#ETCD_CORS=""
#
#[cluster]
#ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380"
# if you use different ETCD_NAME (e.g. test), set ETCD_INITIAL_CLUSTERvalue for this name, i.e. "test=http://..."
#ETCD_INITIAL_CLUSTER="default=http://localhost:2380"
#ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd:2379,http://etcd:4001"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_SRV=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
启动并验证状态(三台都启动)
[root@localhost ~]# systemctl start etcd
[root@localhost ~]# etcdctl settestdir/testkey0 0
0
[root@localhost ~]# etcdctl gettestdir/testkey0
0
[root@localhost ~]# etcdctl -C http://etcd:4001 cluster-health
member 8e9e05c52164694d is healthy: got healthy result fromhttp://0.0.0.0:2379
cluster is healthy
[root@localhost ~]# etcdctl -C http://etcd:2379 cluster-health
member 8e9e05c52164694d is healthy: got healthy result fromhttp://0.0.0.0:2379
cluster is healthy
三、部署master
1、安装Docker
[root@k8s-master ~]# yum install docker
搭建Docker私有仓库
#yum install docker docker-registry -y
systemctl startdocker-distribution
netstat -antp | grep 5000
systemctl enable docker-distribution
私有仓库构建完成。
修改master节点与Node节点的docker配置文件
[root@k8s-master ~]# vim/etc/sysconfig/docker
# /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemonruns
OPTIONS='--selinux-enabled --log-driver=journald--signature-verification=false'
if [ -z "${DOCKER_CERT_PATH}" ]; then
DOCKER_CERT_PATH=/etc/docker
fi
OPTIONS='--insecure-registry 192.168.80.200:5000'
设置开机自启动并开启服务
[root@k8s-master ~]# chkconfig docker on
[root@k8s-master ~]# service docker start
2、安装kubernets
[root@k8s-master ~]# yum install kubernetes
3、配置并启动kubernetes
在kubernetesmaster上需要运行以下组件:
· KubernetsAPI Server
· KubernetsController Manager
· KubernetsScheduler
相应的要更改以下几个配置中带颜色部分信息:
3.1/etc/kubernetes/apiserver
[root@k8s-master ~]# vim /etc/kubernetes/apiserver
###
# kubernetes system config
#
# The following values are used to configure the kube-apiserver
#
# The address on the local server to listen to.
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
# The port on the local server to listen on.
KUBE_API_PORT="--port=8080"
# Port minions listen on
# KUBELET_PORT="--kubelet-port=10250"
# Comma separated list of nodes in the etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://etcd:2379"
# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
# default admission control policies
#KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
# Add your own!
KUBE_API_ARGS=""
3.2/etc/kubernetes/config
[root@k8s-master ~]# vim /etc/kubernetes/config
###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
# kube-apiserver.service
# kube-controller-manager.service
# kube-scheduler.service
# kubelet.service
# kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"
# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"
# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"
# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://k8s-master:8080"
启动服务并设置开机自启动
[root@k8s-master ~]# systemctl enable kube-apiserver.service
[root@k8s-master ~]# systemctl start kube-apiserver.service
[root@k8s-master ~]# systemctl enable kube-controller-manager.service
[root@k8s-master ~]# systemctl start kube-controller-manager.service
[root@k8s-master ~]# systemctl enable kube-scheduler.service
[root@k8s-master ~]# systemctl start kube-scheduler.service
四、部署node
1、安装docker
参见3.1
2、安装kubernets
参见3.2
3、配置并启动kubernetes
在kubernetes node上需要运行以下组件:
· Kubelet
· Kubernets Proxy
相应的要更改以下几个配置文中带颜色部分信息:
3.1/etc/kubernetes/config
[root@K8s-node-1 ~]# vim /etc/kubernetes/config
###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
# kube-apiserver.service
# kube-controller-manager.service
# kube-scheduler.service
# kubelet.service
# kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"
# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"
# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"
# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://k8s-master:8080"
3.2/etc/kubernetes/kubelet
[root@K8s-node-1 ~]# vim /etc/kubernetes/kubelet
###
# kubernetes kubelet (minion) config
# The address for the info server to serve on (set to 0.0.0.0 or"" for all interfaces)
KUBELET_ADDRESS="--address=0.0.0.0"
# The port for the info server to serve on
# KUBELET_PORT="--port=10250"
# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=k8s-node-1"
# location of the api-server
KUBELET_API_SERVER="--api-servers=http://k8s-master:8080"
# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
# Add your own!
KUBELET_ARGS=""
启动服务并设置开机自启动
[root@k8s-master ~]# systemctl enable kubelet.service
[root@k8s-master ~]# systemctl start kubelet.service
[root@k8s-master ~]# systemctl enable kube-proxy.service
[root@k8s-master ~]# systemctl start kube-proxy.service
4、查看状态
在master上查看集群中节点及节点状态
[root@k8s-master ~]# kubectl -shttp://k8s-master:8080 get node
NAME STATUS AGE
k8s-node-1 Ready 3m
k8s-node-2 Ready 16s
[root@k8s-master ~]# kubectl get nodes
NAME STATUS AGE
k8s-node-1 Ready 3m
k8s-node-2 Ready 43s
至此,已经搭建了一个kubernetes集群,但目前该集群还不能很好的工作,请继续后续的步骤。
五、创建覆盖网络——Flannel
1、安装Flannel
在master、node上均执行如下命令,进行安装
[root@k8s-master ~]# yum install flannel
版本为0.0.5
2、配置Flannel
master、node上均编辑/etc/sysconfig/flanneld,修改红色部分
[root@k8s-master ~]# vi /etcs/sysconfig/flanneld
# Flanneld configuration options
# etcd url location. Point this tothe server where etcd runs
FLANNEL_ETCD_ENDPOINTS="http://etcd:2379,http://192.168.8.72:2379,http://192.168.8.74:2379"
# etcd config key. This is theconfiguration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/coreos.com/network"
# Any additional options that you want to pass
FLANNEL_OPTIONS="--logtostderr=false --log_dir=/var/log/k8s/flannel/--etcd-endpoints=http://etcd:2379,http://192.168.8.72:2379,http://192.168.8.74:2379--iface=ens37"
3、配置etcd中关于flannel的key
Flannel使用Etcd进行配置,来保证多个Flannel实例之间的配置一致性,所以需要在etcd上进行如下配置:(‘/coreos.com /network/config’这个key与上文/etc/sysconfig/flannel中的配置项FLANNEL_ETCD_PREFIX是相对应的,错误的话启动就会出错)只需要在master做
[root@k8s-master ~]# etcdctl set /coreos.com/network/config '{"Network": "10.1.0.0/16" }'
{ "Network": "10.1.0.0/16" }
4、启动
启动Flannel之后,需要依次重启docker、kubernete,并且关闭防火墙
启动flannel之后会自动开启防火墙。
在master执行:
systemctl enable flanneld.service
systemctl start flanneld.service
service docker restart
systemctl restart kube-apiserver.service
systemctl restart kube-controller-manager.service
systemctl restart kube-scheduler.service
在node上执行:
systemctl enable flanneld.service
systemctl start flanneld.service
service docker restart
systemctl restart kubelet.service
systemctl restart kube-proxy.service
6.配置nginx
写nginx pod的创建文件(yaml)
[root@k8s-master ~]# cat nginx-rc.yaml
piVersion: v1
kind: ReplicationController
metadata:
name: nginx-controller
spec:
replicas: 2
selector:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
2.创建nodeprot.yaml
[root@k8s-master ~]# cat nginx-server-nodeport.yaml
piVersion: v1
kind: Service
metadata:
name: nginx-service-nodeport
spec:
ports:
- port: 8000
targetPort: 80
protocol: TCP
type: NodePort
selector:
name: nginx
3.创建pod(一定要确认pod的状态为running)
[root@k8s-master ~]# kubectl create -f nginx-rc.yaml
replicationcontroller "nginx-controller" created
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-controller-72rfp 0/1 Container Creating 0 6s
nginx-controller-lsbrt 0/1 ContainerCreating 0 6s
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-controller-72rfp 1/1 Running 0 39s
nginx-controller-lsbrt 1/1 Running 0 39s
注意在创建pod的时候如果pod的状态一直为ContainerCreating,请使用kubectl describe pod 你的podname 查看详细
其中最主要的问题是:details:(open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no suchfile or directory)
解决方案:
查看/etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt(该链接就是上图中的说明)是一个软链接,但是链接过去后并没有真实的/etc/rhsm,所以需要使用yum安装:
yum install *rhsm*
安装完成后,执行一下docker `
js
pullregistry.access.redhat.com/rhel7/pod-infrastructure:latest
如果依然报错,可参考下面的方案:
rpm2cpio python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm | cpio -iv--to-stdout ./etc/rhsm/ca/redhat-uep.pem | tee /etc/rhsm/ca/redhat-uep.pem
这两个命令会生成/etc/rhsm/ca/redhat-uep.pem文件.
顺得的话会得到下面的结果。
[root@k8s-master]# docker pullregistry.access.redhat.com/rhel7/pod-infrastructure:latest
Trying to pull repositoryregistry.access.redhat.com/rhel7/pod-infrastructure ...
latest: Pulling from registry.access.redhat.com/rhel7/pod-infrastructure
26e5ed6899db: Pull complete
66dbe984a319: Pull complete
9138e7863e08: Pull complete
Digest:sha256:92d43c37297da3ab187fc2b9e9ebfb243c1110d446c783ae1b989088495db931
Status: Downloaded newer image for registry.access.redhat.com/rhel7/pod-infrastructure:latest
删除原来创建的rc
[root@k8s-master]# kubectl delete -f mysql-rc.yaml
重新创建
[root@lk8s-master/]# kubectl create -f mysql-rc.yaml
replicationcontroller "mysql" created
再次查看状态
[root@k8s-master ~]# kubectl getpod
NAME READY STATUS RESTARTS AGE
nginx-controller-72rfp 1/1 Running 0 39s
nginx-controller-lsbrt 1/1 Running 0
`
4.查看信息(上方配置没错,输出信息如下)
[root@k8s-master ~]# kubectl describe service nginx-service-nodeport
Name: nginx-service-nodeport
Namespace: default
Labels: <none>
Selector: name=nginx
Type: NodePort
IP: 10.254.112.105
Port: <unset> 8000/TCP
NodePort: <unset> 30519/TCP
Endpoints: 10.1.30.2:80,10.1.68.2:80
Session Affinity: None
No events.
蓝色是docker的IP,红色是映射的端口(映射到真是物理主机的端口),黄色是虚拟IP
5.测试
[root@k8s-master ~]# ping 10.1.30.2
PING 10.1.30.2 (10.1.30.2) 56(84) bytes of data.
64 bytes from 10.1.30.2: icmp_seq=1 ttl=61 time=1.02 ms
^C
--- 10.1.30.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.024/1.024/1.024/0.000 ms
[root@k8s-master ~]# ping 10.1.68.2
PING 10.1.68.2 (10.1.68.2) 56(84) bytes of data.
64 bytes from 10.1.68.2: icmp_seq=1 ttl=61 time=0.793 ms
64 bytes from 10.1.68.2: icmp_seq=2 ttl=61 time=1.37 ms
^C
--- 10.1.68.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.793/1.083/1.373/0.290 ms
[root@k8s-master ~]# curl -i 10.1.30.2
HTTP/1.1 200 OK
Server: nginx/1.15.0
Date: Sun, 17 Jun 2018 16:48:22 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Jun 2018 12:00:18 GMT
Connection: keep-alive
ETag: "5b167b52-264"
Accept-Ranges: bytes 39s
[root@k8s-master ~]# curl -i 10.1.68.2
HTTP/1.1 200 OK
Server: nginx/1.15.0
Date: Sun, 17 Jun 2018 12:24:48 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Jun 2018 12:00:18 GMT
Connection: keep-alive
ETag: "5b167b52-264"
Accept-Ranges: bytes
如上方都没问题,那个恭喜k8s搭建nginx集群你已经成功!!!
本文转自CSDN-K8S集群搭建,并部署nginx实现跨网络访问