首先说一下,下面的内容参考于
这里使用简单的方式 (在centos7下进行安装)
[root@163-44-169-37 ~]# service firewalld stop
or
[root@163-44-169-37 ~]# systemctl disable firewalld
or
[root@163-44-169-37 ~]# systemctl stop firewalld
可以看到安装kubernetes软件包的过程中同时下载的依赖包含如下,其中有docker的安装。
[root@163-44-169-37 ~]# vim /etc/sysconfig/docker
OPTIONS='--selinux-enabled=false --insecure-registry gcr.io'
[root@163-44-169-37 ~]# vim /etc/kubernetes/apiserver
default admission control policies中的
ServiceAccount参数删除
[root@163-44-169-37 ~]# systemctl start etcd
[root@163-44-169-37 ~]# systemctl start docker
[root@163-44-169-37 ~]# systemctl start kube-apiserver
[root@163-44-169-37 ~]# systemctl start kube-controller-manager
[root@163-44-169-37 ~]# systemctl start kube-scheduler
[root@163-44-169-37 ~]# systemctl start kubelet
[root@163-44-169-37 ~]# systemctl start kube-proxy
[root@163-44-169-37 ~]# vim redis-master-controller.yaml
文件内容如下
note:here,you should take care of the marker that indented is strict, you’d used a two spaces instead of a tab.
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: master
image: kubeguide/redis-master
ports:
- containerPort: 6379
[root@163-44-169-37 ~]# kubectl create -f redis-master-controller.yaml
next,查看我们刚刚创建的redis-master和pods.
[root@163-44-169-37 ~]# kubectl get rc
NAME DESIRED CURRENT AGE
redis-master 1 1 7m
[root@163-44-169-37 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-master-k2vlr 1/1 Running 0 9m
运行docker的命令的话会发现
[root@163-44-169-37 ~]# docker ps
CONTAINER ID IMAGE COMMAND
de36d2823bc1 kubeguide/redis-master "redis-server /etc/re"
89c371be051e registry.access.redhat.com/rhel7/pod-infrastructure:latest "/pod"
可以看到docker启动了两个容器,一个是pods,另一个是我们的redis服务
提供redis服务的pod已经创建并正常运行了,接下来创建与之关联的service(服务)——-redis-master的定义文件(文件名为redis-master-service.yaml)
文件内容如下
apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
name: redis-master
spec:
ports:
- port: 6379
targetPort: 6379
selector:
name: redis-master
创建service
[root@163-44-169-37 ~]# kubectl create -f redis-master-service.yaml
service "redis-master" created
查看我们刚刚创建的service
[root@163-44-169-37 ~]# kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 443/TCP 2h
redis-master 10.254.33.208 6379/TCP 5m
注意我们的service被分配了一个虚拟ip10.254.33.208,之后要部署的redis-slave和php-frontend两组pods都将通过10.254.33.208:6379来访问redis-master服务。
note:我们所创建的redis-master的ip地址是随机分配的,那么如何自动化的让我们后面将要启动的两个服务能够得到redis-master的IP地址呢?
kubernetes的解决方案是通过linux的环境变量,在每一个pods的容器里增加环境变量。以此让我们的pods中的其他服务得以知道所要访问的ip.
本例中就应该是
REDIS_MASTER_SERVICE_HOST=10.254.33.208
和
REDIS_MASTER_SERVICE_PORT=6379
[root@163-44-169-37 ~]# vim redis-slave-controller.yaml
redis-slave-controller.yaml的内容如下
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
replicas: 2
selector:
name: redis-slave
template:
metadata:
labels:
name: redis-slave
spec:
containers:
- name: slave
image: kubeguide/guestbook-redis-slave
env:
- name: GET_HOST_FROM
value: env
ports:
- containerPort: 6379
[root@163-44-169-37 ~]# kubectl create -f redis-slave-controller.yaml
replicationcontroller "redis-slave" created
查看RC和pods
[root@163-44-169-37 ~]# kubectl get rc
NAME DESIRED CURRENT AGE
redis-master 1 1 46m
redis-slave 2 2 3m
[root@163-44-169-37 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-master-k2vlr 1/1 Running 0 46m
redis-slave-gdue9 1/1 Running 0 3m
redis-slave-u2m18 1/1 Running 0 3m
[root@163-44-169-37 ~]# kubectl create -f redis-slave-service.yaml
service "redis-slave" created
[root@163-44-169-37 ~]# kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 443/TCP 2h
redis-master 10.254.33.208 6379/TCP 36m
redis-slave 10.254.40.178 6379/TCP 1m
为了实现redis数据库的主从同步,在redis-slave镜像的启动命令/run.sh中,输入如下:
redis-server --slaveof ${REDIS_MASTER_SERVICE_HOST} 6379
我们在观察下docker中的变化
[root@163-44-169-37 ~]# docker ps
CONTAINER ID IMAGE COMMAND
97bd7dab2e22 kubeguide/guestbook-redis-slave "/entrypoint.sh /bin/"
384fc655c097 kubeguide/guestbook-redis-slave "/entrypoint.sh /bin/"
f3a0fccc8b9a registry.access.redhat.com/rhel7/pod-infrastructure:latest "/pod"
5186c37b036e registry.access.redhat.com/rhel7/pod-infrastructure:latest "/pod"
de36d2823bc1 kubeguide/redis-master "redis-server /etc/re"
89c371be051e registry.access.redhat.com/rhel7/pod-infrastructure:latest "/pod"
[root@163-44-169-37 ~]# vim frontend-controller.yaml
[root@163-44-169-37 ~]# kubectl create -f frontend-controller.yaml
replicationcontroller "frontend" created
frontend-controller.yaml内容如下
apiVersion: v1
kind: ReplicationController
metadata:
name: frontend
labels:
name: frontend
spec:
replicas: 3
selector:
name: frontend
template:
metadata:
labels:
name: frontend
spec:
containers:
- name: frontend
image: kubeguide/guestbook-php-frontend
env:
- name: GET_HOST_FROM
value: env
ports:
- containerPort: 80
[root@163-44-169-37 ~]# kubectl get rc
NAME DESIRED CURRENT AGE
frontend 3 3 1m
redis-master 1 1 1h
redis-slave 2 2 26m
[root@163-44-169-37 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
frontend-1csm5 1/1 Running 0 2m
frontend-544p4 1/1 Running 0 2m
frontend-js5df 1/1 Running 0 2m
redis-master-k2vlr 1/1 Running 0 1h
redis-slave-gdue9 1/1 Running 0 27m
redis-slave-u2m18 1/1 Running 0 27m
最后创建service
[root@163-44-169-37 ~]# vim frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
name: frontend
spec:
type: NodePort
ports:
- port: 80
nodePort: 30001
selector:
name: frontend
note:在上述文件中service通过NodePort属性给kubernetes集群中的service映射一个外网可以访问的端口。这里的端口有限制,为(30000~32767)
[root@163-44-169-37 ~]# kubectl create -f frontend-service.yaml
You have exposed your service on an external port on all nodes in your
cluster. If you want to expose this service to the external internet, you may
need to set up firewall rules for the service port(s) (tcp:30001) to serve traffic.
See http://releases.k8s.io/release-1.2/docs/user-guide/services-firewalls.md for more details.
service "frontend" created
提示创建完成,并且给了一个kindly notice.
查看service
[root@163-44-169-37 ~]# kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend 10.254.43.89 nodes 80/TCP 2m
kubernetes 10.254.0.1 <none> 443/TCP 3h
redis-master 10.254.33.208 <none> 6379/TCP 57m
redis-slave 10.254.40.178 <none> 6379/TCP 22m
另外这个例子中的controller.js有一个错误的
修改过程如下(最好是在镜像中修改,否则得分别对三个service服务修改3次)
[root@163-44-169-37 ~]# docker ps
[root@163-44-169-37 ~]# docker exec -ti 容器id /bin/bash
root@frontend-1csm5:/var/www/html# apt-get -y install vim
root@frontend-1csm5:/var/www/html# vim controllers.js
修改27行的
data.data.split(",");改为data.split(",");
root@frontend-1csm5:/var/www/html# exit
演示图如下:
Node,Pod,Replication Controller,Service
相对于master而言的物理机或者虚拟机,
其拥有:
1. 启动和管理pod的服务—kuberlet
2. kube-proxy
3. docker daemon
结构:
1. Node地址 主机的ip地址,或者Node ID
2. Node运行状态: (Pending,Running,Terminated)
3. Node Condition 目前只有一种Ready
4. Node系统容量:可用系统资源,包括cpu,内存数量,最大可调度Pod数量
5. 其他:内核版本号,Kubernetes版本号,Docker版本号,操作系统名称.
查看node信息
[root@163-44-169-37 ~]# kubectl describe node
node controller是kubernetes的一个组件,用于对node管理
1. 集群范围内node信息同步
2. 单个node的生命周期管理
node注册
kubenetes的推荐注册方式
kubelet自注册参数
option | description |
---|---|
- -apiserver=: | apiserver的地址 |
- -kubeconfig=: | 登陆apiserver所需凭据/证书的目录 |
- -cloud_provider=: | 云服务商地址,用于获取自身的metadata |
- -register-node=: | 设置为true表示自动注册到apiserver |
pod的出现是为了解决docker隔离容器之间必须通过link方式才能互相访问的问题。
一个pod中的应用容器共享同一组资源
- PID命名空间:可以看到其它应用程序的进程ID
- 网络命名空间:能够访问同一个ip和端口范围
- IPC命名空间:能够使用SystemV IPC或POSIX消息队列进行通信
- UTS命名空间:共享主机名
- Volumes(共享存储卷):能够访问POD级别定义的Volumes
生命周期交由replication controller管理,所含容器运行结束后,pod也结束。
pod的状态
status | description |
---|---|
pending | 其所包含的容器镜像还未完全创建 |
running | 其所包含的容器镜像创建完成并成功运行起来 |
succeeded | 所有容器都成功结束,并且不会被重启 |
failed | 所有容器都结束了,但是至少有一个容器是以失败状态结束的 |
负责定义对象的属性
通过label selector来选择对象
包括两种选择方式
1. Equality-based
name = redis-slave
name != redis-slave
2. Set-based
name in (reids-master,redis-slave)
name not in (reids-master,redis-slave)
label与label selector共同组成了kubernetes中的最核心的应用模型,使得被管理的对象能够被精细的分组管理,同时实现了整个集群的高可用性。
用于定义Pod副本的数量,在master内,controller manager进程通过RC的定义来完成Pod的创建,监控,启停等操作。
如果某个pod停止运行,就会将pod重启命令提交给node上的某个程序来完成(如kubelet或docker)
综上所述:
通过对RC的使用,kubernetes实现了应用集群的高可用性,并且大大减少了系统管理员在传统IT环境中需要完成的许多手工运维工作(如主机监控脚本,应用监控脚本,故障恢复脚本等)
如果总共有三个node,其中node1和node2上运行着redis服务,node2节点down掉,cabernets会自动创建并启动新的pod,可能在node3,也可能在node1上。
pod scaling
[root@163-44-169-37 ~]# kubectl scale rc redis-slave --replicas=3
删除RC并不会影响通过该RC已经创建好的pod,为了删除所有的pod,可以通过设置replicas值为0,然后更新该RC.另外客户端工具kubectl提供了stop和delete命令来完成一次性删除RC和RC控制的全部pod。
一个service可以看作一组提供相同服务的pod的对外访问接口。service作用于哪些pod是通过label selector来定义的
这样service与service之间访问的时候就不会关心底层到底访问的那个pod。
在pod正常启动后,系统会根据service的定义创建出与pod对应的endpoint对象,
以建立起service与后端pod的对应关系,随着pod的创建,销毁,endpoint对象也将被更新,endpoint对象主要由pod的IP地址和容器需要监听的端口号组成。通过以下指令查看endpoint对象
[root@163-44-169-37 ~]# kubectl get endpoints
NAME ENDPOINTS AGE
frontend 172.17.0.5:80,172.17.0.6:80,172.17.0.7:80 3h
kubernetes 163.44.169.37:6443 6h
redis-master 172.17.0.2:6379 3h
redis-slave 172.17.0.3:6379,172.17.0.4:6379 3h
pod IP地址和service的cluster ip地址不同
pod:docker deamon根据docker0网桥的IP地址段进行分配的。
service:kubernetes系统中的虚拟ip地址,由系统动态分配。
一般,service的生命周期长于pod,pod会根据实际情况而被replication controller销毁,再次创建。
service如何实现外部访问?
1. NodePort
spec.type = NodePort
spec.ports.nodePort
2. LoadBalancer
spec.type = LoadBalancer
spec.ports.nodePort
status.loadBalancer.ingress.ip(设置为云服务商提供的负载均衡器的IP地址)
Pod分配到node时创建的,pod从node上移除,EmptyDir中的数据也会永久移除。
作用:
1. 临时空间(某些应用程序所需,无需长久保存)
2. 长时间任务的中间过程,CheckPoint临时保存目录
3. 同一个pod内,多容器共享目录
在pod上挂载宿主机上的文件夹或目录。
作用:
1. 容器应用程序生成的日志文件需要永久保存。
2. 需要访问宿主机上的docker引擎内部数据结构的容器应用
使用谷歌计算引擎(Google Compute Engine,GCE)上永久磁盘上的文件。
1. node需要是GCE虚拟机
2. 这些虚拟机需要与PD存在于相同的GCE项目和Zone中。
通过gcloud命令即可创建一个PD
gcloud compute disks create --size=500GB --zone=us-centrall-a my-data-disk
和上面的gce类似,需要使用Amazon提供的Amazon Web Services(AWS)的EBS Volume。
通过aws ec2 create-volume命令创建一个EBS volume
was ec2 create-volume --availability-zone eu-west-la --size 10 --volume-type gp2
使用iSCSI存储设备上的目录挂载到Pod中。
使用开源的GlusterFS网络文件系统的目录挂载到Pod中。
使用linux块设备共享存储(Rados Block Device)挂载到Pod中
通过挂载一个空目录,并从git库中clone一个git repository以供Pod使用
tmfs(内存文件系统实现)
通常是一种网络存储,例如GCEPersistentDisk.AWSElasticBlockStore,NFS,iSCSI等。
[root@163-44-169-37 ~]# kubectl get namespaces
NAME STATUS AGE
default Active 7h
创建新的namespace
[root@163-44-169-37 ~]# vim namespace-dev.yaml
[root@163-44-169-37 ~]# kubectl create -f namespace-dev.yaml
namespace "development" created
namespace-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
name: development
在创建pod的时候可以指定pod属于哪个namespace。
这样的话使用# kubectl get pods讲无法显示。
命令需要改为# kubectl get pods –namespace=development
可以通过namespace来实现用户分组,即”多租户”管理。对不同的租户还可以进行单独的资源配额设置和管理。
与label类似
用户任意定义的附加信息。
以便于外部工具进行查找。
记录的信息如下:
1. build信息、release信息、docker镜像信息
2. 日志库、监控库、分析库等资源库的地址信息
3. 程序调试工具信息,例如工具名称,版本号
4. 团队的联系信息,例如电话号码、负责人名称、网址等
下面是一个大致的流程图
kubernetes的工作是由
1. API Server:提供资源对象的唯一操作入口,全量查询+变化监听
2. Controller Manager:集群内部的管理控制中心,故障检测和恢复的自动化工作。
3. Scheduler:集群的调度器,负责Pod在集群节点中的调度分配
4. Kubelet:负责本节点上的Pod的创建、修改、监控、删除等全生命周期的管理。同时定时上报本Node的信息到API Server里
5. Proxy:实现了service的代理以及软件模式的负载均衡器
6. kubectl:客户端工具,访问kubernetes系统
Node节点运行的Kubelet服务中内嵌了一个cAdvisor服务,用于实时监控Docker上运行的容器的性能指标。
cAdvisor是google的另一个开源项目。