Kubernetes1.5.2 HA 部署篇
节点信息kubernetes 1.5.2版本每个节点都要有:vim /etc/hosts10.30.30.116k8s-master-116etcd10.30.30.117k8s-master-117etcd10.30.30.118k8s-master-118etcd10.30.30.119k8s-prod...
节点信息
kubernetes 1.5.2版本
每个节点都要有:vim /etc/hosts
10.30.30.116 | k8s-master-116 | etcd |
10.30.30.117 | k8s-master-117 | etcd |
10.30.30.118 | k8s-master-118 | etcd |
10.30.30.119 | k8s-produce-119 | |
10.30.30.131 | k8s-produce-131 | |
10.30.30.135 | k8s-nginx-135 |
一.etcd 集群部署
10.30.30.116,10.30.30.117,10.30.30.118:先部署etcd集群参考etcd-3.3.11 集群_码农崛起-CSDN博客_etcd集群读写
依次启动etcd服务
systemctl enable etcd;sysetmctl start etcd
[root@k8s-master-116 kubernetes]# etcdctl member list
4fe172c7048d8e9: name=k8s-master-118 peerURLs=http://k8s-master-118:2380 clientURLs=http://k8s-master-118:2379,http://k8s-master-118:4001 isLeader=false
52a0567b30f175d3: name=k8s-master-117 peerURLs=http://k8s-master-117:2380 clientURLs=http://k8s-master-117:2379,http://k8s-master-117:4001 isLeader=false
d092ee3af52b994d: name=k8s-master-116 peerURLs=http://k8s-master-116:2380 clientURLs=http://k8s-master-116:2379,http://k8s-master-116:4001 isLeader=true
二 kubernetes master 部署
在10.30.30.116,10.30.30.117,10.30.30.118
systemctl stop firewalld.service && systemctl disable firewalld.service
sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
yum -y install wget net-tools ntp ntpdate lrzsz
systemctl restart ntpdate.service ntpd.service && systemctl enable ntpd.service ntpdate.service
hostnamectl --static set-hostname k8s-master-116
hostnamectl --static set-hostname k8s-master-117
hostnamectl --static set-hostname k8s-master-118
在 master 的虚机上,需要运行三个组件:Kubernets API Server、Kubernets Controller Manager、Kubernets Scheduler。
1. 安装 kubernetes docker ,设置开机自启动并开启服务
[root@k8s ~]# yum -y install kubernetes-master kubernetes-client(kubectl) docker flannel
[root@k8s ~]# systemctl start docker.service //我这里的宿主机磁盘空间不够导致docker服务起不来,清理足够的磁盘空间就可以了
1.1首先修改 /etc/kubernetes/apiserver 文件:
k8s-master-116、k8s-master-117、k8s-master-118的配置一样:
[root@k8s-master-116 kubernetes]# cat apiserver | grep -v "#"
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
KUBE_API_PORT="--port=8080"
KUBE_ETCD_SERVERS="--etcd-servers=http://etcd:2379" (是个集群)
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
KUBE_API_ARGS="--service-node-port-range=1-65535"
1.2 接着修改 /etc/kubernetes/config 文件,
这个文件是综合文件,Kubernets API Server、Kubernets Controller Manager、Kubernets Scheduler,kube-proxy,kubelet都使用
[root@k8s-master-116 kubernetes]# cat config | grep -v "#"
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"(根据情况调整为true,类似docker 里面的privileged=true)
KUBE_MASTER="--master=http://etcd:8080"(集群信息,也可以是haproxy代理地址)
不修改就看系统是否默认是--address=127.0.0.1 --leader-elect=true 状态
1.修改controller-manager和scheduler配置文件
[root@k8s-master-116 kubernetes]# cat controller-manager
###
# The following values are used to configure the kubernetes controller-manager
# defaults from config and apiserver should be adequate
# Add your own!
#KUBE_CONTROLLER_MANAGER_ARGS="--address=127.0.0.1 --leader-elect=true"
[root@k8s-master-116 kubernetes]# cat scheduler
###
# kubernetes scheduler config
# default config should be adequate
# Add your own!
KUBE_SCHEDULER_ARGS="--address=127.0.0.1 --leader-elect=true"
让节点有选举master leader 功能,ok master配置完成
1.3 修改 /etc/sysconfig/flanneld
[root@k8s-master-116 kubernetes]# cat /etc/sysconfig/flanneld |grep -v "#"
FLANNEL_ETCD_ENDPOINTS="http://etcd:2379"
FLANNEL_ETCD_PREFIX="/atomic.io/network"
[root@k8s-master-116 kubernetes]# etcdctl mk /atomic.io/network/config '{ "Network": "10.0.0.0/16" }'
{ "Network": "10.0.0.0/16" }
三个节点启动
systemctl start flanneld
systemctl start docker
systemctl start kube-apiserver kube-controller-manager kube-scheduler
1.4 查看leader信息位于哪个节点
[root@k8s-master-117 kubernetes]# tail -f /var/log/messages
Jun 24 10:29:14 k8s-master-117 kube-controller-manager: E0624 10:29:14.539355 10807 controllermanager.go:558] Failed to start certificate controller: open /etc/kubernetes/ca/ca.pem: no such file or directory
Jun 24 10:29:14 k8s-master-117 kube-controller-manager: I0624 10:29:14.542292 10807 serviceaccounts_controller.go:120] Starting ServiceAccount controller
Jun 24 10:29:14 k8s-master-117 kube-controller-manager: I0624 10:29:14.550451 10807 garbagecollector.go:766] Garbage Collector: Initializing
Jun 24 10:29:16 k8s-master-117 kube-scheduler: I0624 10:29:16.762964 10808 leaderelection.go:247] lock is held by k8s-master-118 and has not yet expired
Jun 24 10:29:19 k8s-master-117 kube-scheduler: I0624 10:29:19.068635 10808 leaderelection.go:247] lock is held by k8s-master-118 and has not yet expired
Jun 24 10:29:21 k8s-master-117 kube-scheduler: I0624 10:29:21.745470 10808 leaderelection.go:247] lock is held by k8s-master-118 and has not yet expired
Jun 24 10:29:22 k8s-master-117 kube-apiserver: W0624 10:29:22.574708 10805 controller.go:392] Resetting endpoints for master service "kubernetes" to &TypeMeta{Kind:,APIVersion:,}
Jun 24 10:29:24 k8s-master-117 kube-controller-manager: I0624 10:29:24.550622 10807 garbagecollector.go:780] Garbage Collector: All monitored resources synced. Proceeding to collect garbage
Jun 24 10:29:24 k8s-master-117 kube-scheduler: I0624 10:29:24.731674 10808 leaderelection.go:247] lock is held by k8s-master-118 and has not yet expired
Jun 24 10:29:27 k8s-master-117 kube-scheduler: I0624 10:29:27.776649 10808 leaderelection.go:247] lock is held by k8s-master-118 and has not yet expired
Jun 24 10:29:31 k8s-master-117 kube-scheduler: I0624 10:29:31.278528 10808 leaderelection.go:247] lock is held by k8s-master-118 and has not yet expired
Jun 24 10:29:32 k8s-master-117 kube-apiserver: W0624 10:29:32.585959 10805 controller.go:392] Resetting endpoints for master service "kubernetes" to &TypeMeta{Kind:,APIVersion:,}
Jun 24 10:29:34 k8s-master-117 kube-scheduler: I0624 10:29:34.600337 10808 leaderelection.go:247] lock is held by k8s-master-118 and has not yet expired
[root@k8s-master-116 kubernetes]# kubectl -n kube-system get ep kube-controller-manager -o yaml
apiVersion: v1
kind: Endpoints
metadata:
annotations:
control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"k8s-master-116","leaseDurationSeconds":15,"acquireTime":"2019-06-24T02:24:14Z","renewTime":"2019-06-24T02:28:29Z","leaderTransitions":0}'
creationTimestamp: 2019-06-24T02:24:14Z
name: kube-controller-manager
namespace: kube-system
resourceVersion: "366"
selfLink: /api/v1/namespaces/kube-system/endpoints/kube-controller-manager
uid: 28ba9170-9627-11e9-9c2e-005056a98475
subsets: []
[root@k8s-master-116 kubernetes]# kubectl -n kube-system get ep kube-scheduler -o yaml
apiVersion: v1
kind: Endpoints
metadata:
annotations:
control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"k8s-master-116","leaseDurationSeconds":15,"acquireTime":"2019-06-24T02:24:14Z","renewTime":"2019-06-24T02:28:45Z","leaderTransitions":0}'
creationTimestamp: 2019-06-24T02:24:14Z
name: kube-scheduler
namespace: kube-system
resourceVersion: "387"
selfLink: /api/v1/namespaces/kube-system/endpoints/kube-scheduler
uid: 28b9a872-9627-11e9-9c2e-005056a98475
subsets: []
1.5 我们关掉一台集群,测试集群创建yaml看看会怎么样
[root@k8s-master-117 kubernetes]# kubectl -n kube-system get ep kube-controller-manager -o yaml
apiVersion: v1
kind: Endpoints
metadata:
annotations:
control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"k8s-master-117","leaseDurationSeconds":15,"acquireTime":"2019-06-24T02:29:14Z","renewTime":"2019-06-24T02:31:05Z","leaderTransitions":0}'
creationTimestamp: 2019-06-24T02:29:14Z
name: kube-controller-manager
namespace: kube-system
resourceVersion: "573"
selfLink: /api/v1/namespaces/kube-system/endpoints/kube-controller-manager
uid: dbadb031-9627-11e9-9c2e-005056a98475
subsets: []
[root@k8s-master-117 kubernetes]# kubectl -n kube-system get ep kube-scheduler -o yaml
apiVersion: v1
kind: Endpoints
metadata:
annotations:
control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"k8s-master-118","leaseDurationSeconds":15,"acquireTime":"2019-06-24T02:29:15Z","renewTime":"2019-06-24T02:31:12Z","leaderTransitions":0}'
creationTimestamp: 2019-06-24T02:29:15Z
name: kube-scheduler
namespace: kube-system
resourceVersion: "581"
selfLink: /api/v1/namespaces/kube-system/endpoints/kube-scheduler
uid: dc442ece-9627-11e9-9016-005056a91e7b
subsets: []
可以看到 controller-manager和 scheduler已转移到其他节点
三、部署 node
安装 docker,kubernetes-node ,设置开机自启动并开启服务
yum install docker kubernetes-node flannel -y
systemctl start docker && systemctl enable docker
在 node 的虚机上,需要运行三个组件:Kubelet、Kubernets Proxy。
1.1 修改flanneld
[root@k8s-produce-119 kubernetes]# cat /etc/sysconfig/flanneld | grep -v "#"
FLANNEL_ETCD_ENDPOINTS="http://etcd:2379"
FLANNEL_ETCD_PREFIX="/atomic.io/network"
systemctl start flannled
1.2 首先修改 /etc/kubernetes/config 文件:(注意:这里配置的是etcd的地址,也就是master1/2/3的地址其中之一)
[root@k8s-produce-119 kubernetes]# cat config | grep -v "#"
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://etcd:8080"(master也就是api-server的集群地址)
1.3 接着修改 /etc/kubernetes/kubelet 文件:(注:--hostname-override= 对应的node机器)
[root@k8s-produce-119 kubernetes]# cat kubelet |grep -v "#"
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_PORT="--port=10250"
KUBELET_HOSTNAME="--hostname-override=k8s-produce-119"
KUBELET_API_SERVER="--api-servers=http://etcd:8080"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
KUBELET_ARGS="--cluster_dns=10.254.254.254 --cluster_domain=jettech.com"
systemctl start kubelet kube-proxy
1.4. 查看集群状态
在任意一台master上查看集群中节点及节点状态:
[root@k8s ~]# kubectl get node
[root@k8s-master-116 kubernetes]# kubectl get nodes
NAME STATUS AGE
k8s-produce-119 Ready 2m
参考:
1、kubernetes 1.5.2原理以及集群HA部署_大坏蛋的博客-CSDN博客
k8s kubernetes 高可用https and http集群实战 HA_小刚的博客-CSDN博客
四,在kubernetes上运行一个容器之案例
1. 检查kubernetes 组件是否正常运行。
root@c720120 ~]# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}
etcd-1 Healthy {"health": "true"}
etcd-2 Healthy {"health": "true"}
---------------------
2. 检查kubernetes master状态
[root@k8s-master-116 kubernetes]# kubectl cluster-info
Kubernetes master is running at http://localhost:8080
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
[root@k8s-master-116 kubernetes]#
3.运行一个nginx的容器案例
kubectl run my-first-nginx --image=nginx --replicas=2 --port=80
deployment.apps "my-first-nginx" created
4. 查看所有的pods.
[root@k8s-master-116 kubernetes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-first-nginx-3504586902-905bn 1/1 Running 0 25s 10.0.10.3 k8s-produce-119
my-first-nginx-3504586902-z3rnr 1/1 Running 0 25s 10.0.10.2 k8s-produce-11
5,查看所有的deployment
[root@k8s-master-116 kubernetes]# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
my-first-nginx 2 2 2 2 42s
[root@k8s-master-116 kubernetes]#
6,映射端口到外部,让用户能够访问该服务
kubectl expose deployment my-first-nginx --port=80 --type=LoadBalancer
service "my-first-nginx" exposed
7, 查看发布的服务
[root@k8s-master-116 kubernetes]# kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 26m
my-first-nginx 10.254.53.226 <pending> 80:28642/TCP 22s
8,停止应用
kubectl delete deployment my-first-nginx
kubectl delete service my-first-nginx
9,可以查看创建的服务详细信息
[root@k8s-master-116 kubernetes]# kubectl describe service my-first-nginx
Name: my-first-nginx
Namespace: default
Labels: run=my-first-nginx
Selector: run=my-first-nginx
Type: LoadBalancer
IP: 10.254.53.226
Port: <unset> 80/TCP
NodePort: <unset> 28642/TCP
Endpoints: 10.0.10.2:80,10.0.10.3:80
Session Affinity: None
No events.
10,用浏览器进行校验下服务
10.30.30.116,10.30.30.117,10.30.30.118随便关机都不影响10.30.30.119:28642的访问
11.部署ingress
kubernetes service五种访问方式
1、ClusterIP
ClusterIP服务是Kuberntets的默认服务。它在集群内部生成一个服务,供集群内的其他应用访问。外部无法访问。
apiVersion: v1
kind: Service
metadata:
name: my-internal-service
selector:
app: my-app
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
这种方式也可以通过外部网络访问,不过需要使用kubernetes proxy来访问:
开启proxy
kubectl proxy --port=8080
现在可以通过Kubernetes API使用下面这个地址来访问这个服务:
http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/
何时使用这种方式?
有一些场景下,你得使用 Kubernetes 的 proxy 模式来访问你的服务:
- 由于某些原因,你需要调试你的服务,或者需要直接通过笔记本电脑去访问它们。
- 容许内部通信,展示内部仪表盘等。
这种方式要求我们运行 kubectl 作为一个未认证的用户,因此我们不能用这种方式把服务暴露到 internet 或者在生产环境使用。
2、NodePort
NodePort服务是让外部流量直接访问服务的最原始方式。NodePort,顾名思义,在所有的节点(虚拟机)上开放指定的端口,所有发送到这个端口的流量都会直接转发到服务。
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
selector:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TCP
NodePort服务有两个地方不同于一般的“ClusterIP”服务。首先,它的类型是“NodePort”。还有一个叫做“nodePort"的端口,能在节点上指定开放哪个端口。如果没有指定端口,它会选择一个随机端口 ( 只能使用30000–32767的端口 )
如果节点 / 虚拟机的IP地址发生变化,需要进行处理
何时使用这种方式?
这种方法有许多缺点:
- 每个端口只能是一种服务
- 端口范围只能是 30000-32767
- 如果节点/VM 的 IP 地址发生变化,你需要能处理这种情况。
基于以上原因,我不建议在生产环境上用这种方式暴露服务。如果你运行的服务不要求一直可用,或者对成本比较敏感,你可以使用这种方法。这样的应用的最佳例子是 demo 应用,或者某些临时应用。
3、LoadBalancer
LoadBalancer服务是发布服务到互联网的标准方式。在GKE中,它会启动一个Network Load Balancer,分配一个单独的IP地址,将所有流量转发到服务中。
何时使用这种方式?
如果你想要直接暴露服务,这就是默认方式。所有通往你指定的端口的流量都会被转发到对应的服务。它没有过滤条件,没有路由等。这意味着你几乎可以发送任何种类的流量到该服务,像 HTTP,TCP,UDP,Websocket,gRPC 或其它任意种类。
这个方式的最大缺点是每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是非常昂贵的。
4、ExternalName类型
这种方式主要是通过CNAME实现的,在kubernetes 1.7.x以及以上才支持这种方式,例如:
这种类型其实是一个没有 selector 的 Service
apiVersion: v1
kind: Service
metadata:
name: pinpoint
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
应用场景:
Servcie 抽象了该如何访问 Kubernetes Pod,但也能够抽象其它类型的 backend,例如:
(1)、希望在生产环境中使用外部的数据库集群,但测试环境使用自己的数据库。
(2)、希望服务指向另一个 Namespace 中或其它集群中的服务。
(3)、正在将工作负载转移到 Kubernetes 集群,和运行在 Kubernetes 集群之外的 backend。
由于这个 Service 没有 selector,就不会创建相关的 Endpoints 对象。可以手动将 Service 映射到指定的 Endpoints:(即手动创建endpoint,由于名字相同会进行自动映射)
kind: Endpoints
apiVersion: v1
metadata:
name: pinpoint
subsets:
- addresses:
- ip: 192.168.2.58
ports:
- port: 80
说明:addresses后面的ip就是外接服务的访问ip,可以接多个,可以是外接服务公网IP或者可以访问的私网IP
访问没有 selector 的 Service,与有 selector 的 Service 的原理相同。请求将被路由到用户定义的 Endpoint。(上面的例子则是路由到 192.168.2.58:80)
注意:Endpoint IP 地址不能是 loopback(127.0.0.0/8)、 link-local(169.254.0.0/16)、或者 link-local 多播(224.0.0.0/24)。
ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。 相反地,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
当查询主机 my-service.prod.svc.CLUSTER时,集群的 DNS 服务将返回一个值为 my.database.example.com 的 CNAME 记录。 访问这个服务的工作方式与其它的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。
创建了没有selector的service之后,还需要手动创建endpoint才可以被实际调用。
5、Ingress
Ingress (ingress后面需要接service作为后端应用)
Ingress实际上不是一种服务。相反,它在多个服务前面充当“智能路由”的角色,或者是集群的入口。
使用Ingress可以做很多事情,不同类型的Ingress控制器有不同的功能。
默认的GKE ingress控制器会启动一个 HTTP(S) Load Balancer,可以通过基于路径或者是基于子域名的方式路由到后端服务。例如,可以通过foo.yourdomain.com 发送任何东西到foo服务,或者是发送yourdomain.com/bar/路径下的任何东西到bar服务。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: other
servicePort: 8080
rules:
- host: foo.mydomain.com
http:
paths:
- backend:
serviceName: foo
servicePort: 8080
- host: mydomain.com
http:
paths:
- path: /bar/*
backend:
serviceName: bar
servicePort: 8080
Ingress可能是发布服务最强大的方式,同时也是最复杂的。Ingress控制器的类型很多,如 Google Cloud Load Balancer,Nginx,Contour,Istio等等。还有一些Ingress控制器插件,比如证书管理器,可以自动为服务提供SSL认证。
如果想在同一个IP地址下发布多个服务,并且这些服务使用相同的第 7 层协议(通常是 HTTP),Ingress是最有用的。如果使用原生的GCP集成,只需要支付一个负载均衡器的费用。因为Ingress是“智能”的,你可以得到很多开箱即用的特性(比如SSL、认证、路由等)。
参考kubernetes service四种访问方式 - 简书
参考Kubernetes的三种外部访问方式:NodePort、LoadBalancer 和 Ingress - DockOne.io
5.1、Ingress 简介
Ingress 组成
ingress controller
将新加入的Ingress转化成Nginx的配置文件并使之生效
ingress服务
将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可
Ingress 工作原理
1.ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化,
2.然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,
3.再写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,
4.然后reload一下使配置生效。以此达到域名分配置和动态更新的问题。
ingress可以实现使用nginx等开源的反向代理负载均衡器实现对外暴露服务,可以理解Ingress就是用于配置域名转发的一个东西,在nginx中就类似upstream,它与ingress-controller结合使用,通过ingress-controller监控到pod及service的变化,动态地将ingress中的转发信息写到诸如nginx、apache、haproxy等组件中实现方向代理和负载均衡。
1.动态配置服务
如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要而外的操作.
2.减少不必要的端口暴露
配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式
5.2、什么是Ingress?
从前面的学习,我们可以了解到Kubernetes
暴露服务的方式目前只有三种:LoadBlancer Service、ExternalName、NodePort Service、Ingress
;而我们需要将集群内服务提供外界访问就会产生以下几个问题:
5.2.1、Pod 漂移问题
Kubernetes 具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,还可以动态扩容等,通俗地说,这个 Pod 可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着 Pod 的创建和销毁,Pod IP 肯定会动态变化;那么如何把这个动态的 Pod IP 暴露出去?这里借助于 Kubernetes 的 Service 机制,Service 可以以标签的形式选定一组带有指定标签的 Pod,并监控和自动负载他们的 Pod IP,那么我们向外暴露只暴露 Service IP 就行了;这就是 NodePort 模式:即在每个节点上开起一个端口,然后转发到内部 Pod IP 上,如下图所示:
此时的访问方式:http://nodeip:nodeport/
5.2.2、端口管理问题
采用 NodePort 方式暴露服务面临问题是,服务一旦多起来,NodePort 在每个节点上开启的端口会及其庞大,而且难以维护;这时,我们可以能否使用一个Nginx直接对内进行转发呢?众所周知的是,Pod与Pod之间是可以互相通信的,而Pod是可以共享宿主机的网络名称空间的,也就是说当在共享网络名称空间时,Pod上所监听的就是Node上的端口。那么这又该如何实现呢?简单的实现就是使用 DaemonSet 在每个 Node 上监听 80,然后写好规则,因为 Nginx 外面绑定了宿主机 80 端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应 Service IP 就行了,如下图所示:
5.2.3、域名分配及动态更新问题
从上面的方法,采用 Nginx-Pod 似乎已经解决了问题,但是其实这里面有一个很大缺陷:当每次有新服务加入又该如何修改 Nginx 配置呢??我们知道使用Nginx可以通过虚拟主机域名进行区分不同的服务,而每个服务通过upstream进行定义不同的负载均衡池,再加上location进行负载均衡的反向代理,在日常使用中只需要修改nginx.conf即可实现,那在K8S中又该如何实现这种方式的调度呢???
假设后端的服务初始服务只有ecshop,后面增加了bbs和member服务,那么又该如何将这2个服务加入到Nginx-Pod进行调度呢?总不能每次手动改或者Rolling Update 前端 Nginx Pod 吧!!此时 Ingress 出现了,如果不算上面的Nginx,Ingress 包含两大组件:Ingress Controller 和 Ingress。
Ingress 简单的理解就是你原来需要改 Nginx 配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改 Nginx 了,直接改 yaml 然后创建/更新就行了;那么问题来了:”Nginx 该怎么处理?”
Ingress Controller 这东西就是解决 “Nginx 的处理方式” 的;Ingress Controoler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下,工作流程如下图:
实际上Ingress也是Kubernetes API的标准资源类型之一,它其实就是一组基于DNS名称(host)或URL路径把请求转发到指定的Service资源的规则。用于将集群外部的请求流量转发到集群内部完成的服务发布。我们需要明白的是,Ingress资源自身不能进行“流量穿透”,仅仅是一组规则的集合,这些集合规则还需要其他功能的辅助,比如监听某套接字,然后根据这些规则的匹配进行路由转发,这些能够为Ingress资源监听套接字并将流量转发的组件就是Ingress Controller。
PS:Ingress 控制器不同于Deployment 控制器的是,Ingress控制器不直接运行为kube-controller-manager的一部分,它仅仅是Kubernetes集群的一个附件,类似于CoreDNS,需要在集群上单独部署。
参考Kubernetes学习之路(十五)之Ingress和Ingress Controller - 烟雨浮华 - 博客园
cat default-backend.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: default-http-backend
labels:
k8s-app: default-http-backend
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: default-http-backend
spec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backend
image: docker.io/cdchen/defaultbackend:1.0
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 8080
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
nodeSelector:
kubernetes.io/hostname: k8s-nginx-135
---
apiVersion: v1
kind: Service
metadata:
name: default-http-backend
namespace: kube-system
labels:
k8s-app: default-http-backend
spec:
ports:
- port: 80
targetPort: 8080
selector:
k8s-app: default-http-backend
cat nginx-ingress-controller.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-ingress-controller
labels:
k8s-app: nginx-ingress-controller
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: nginx-ingress-controller
annotations:
prometheus.io/port: '10254'
prometheus.io/scrape: 'true'
spec:
hostNetwork: true
terminationGracePeriodSeconds: 60
containers:
- image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.9.0-beta.10
name: nginx-ingress-controller
readinessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
livenessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 1
ports:
- containerPort: 80
hostPort: 80
- containerPort: 443
hostPort: 443
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
- --apiserver-host=http://10.30.30.116:8080
nodeSelector:
kubernetes.io/hostname: k8s-nginx-135
使用 3个应用 三个ingress规则 一个对外提供的统一访问入口(可选service-nodeport.yaml)
1)cat kubernetes-dashboard.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
labels:
app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: kubernetes-dashboard
template:
metadata:
labels:
app: kubernetes-dashboard
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "dedicated",
"operator": "Equal",
"value": "master",
"effect": "NoSchedule"
}
]
spec:
containers:
- name: kubernetes-dashboard
image: hub.c.163.com/allan1991/kubernetes-dashboard-amd64:v1.5.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9090
protocol: TCP
args:
- --apiserver-host=http://10.30.30.116:8080
livenessProbe:
httpGet:
path: /
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
---
kind: Service
apiVersion: v1
metadata:
labels:
app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
ports:
- port: 80
targetPort: 9090
selector:
app: kubernetes-dashboard
2)cat jenkins-app.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jenkins
namespace: kube-system
labels:
k8s-app: jenkins
spec:
replicas: 1
selector:
matchLabels:
k8s-app: jenkins
template:
metadata:
labels:
k8s-app: jenkins
spec:
containers:
- name: jenkins
image: hub.c.163.com/library/jenkins:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
- name: maven-repository
mountPath: /opt/maven/repository
- name: docker
mountPath: /usr/bin/docker
- name: docker-sock
mountPath: /var/run/docker.sock
ports:
- containerPort: 8080
- containerPort: 50000
volumes:
- name: jenkins-home
hostPath:
path: /ceph/jenkins_home
- name: maven-repository
hostPath:
path: /ceph/maven/repository
- name: docker
hostPath:
path: /usr/bin/docker
- name: docker-sock
hostPath:
path: /var/run/docker.sock
nodeSelector:
kubernetes.io/hostname: k8s-produce-131
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: jenkins
name: jenkins
namespace: kube-system
annotations:
prometheus.io/scrape: 'true'
spec:
ports:
- name: jenkins
port: 80
nodePort: 31888
targetPort: 8080
protocol: TCP
- name: jenkins-agent
port: 50000
targetPort: 50000
type: LoadBalancer
selector:
k8s-app: jenkins
3)cat tomcat-demo.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat-deploy
#namespace: default
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: tomcat
release: canary
template:
metadata:
labels:
app: tomcat
release: canary
spec:
containers:
- name: tomcat
image: tomcat:8.5.34-jre8-alpine
ports:
- name: http
containerPort: 8080
name: ajp
containerPort: 8009
---
kind: Service
apiVersion: v1
metadata:
name: tomcat
#namespace: default
namespace: kube-system
spec:
selector:
app: tomcat
release: canary
#type: NodePort
ports:
- name: http
targetPort: 8080
#nodePort: 38080
port: 8080
- name: ajp
targetPort: 8009
#nodePort: 38009
port: 8009
---
cat jenkins-ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: jenkins-ingress
#namespace: default
namespace: kube-system(要和服务的命名空间一致)
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
#nginx.ingress.kubernetes.io/configuration-snippet: |
#rewrite /(wubo*) login/wubo break;
#if ($request_uri = '/?%login') { rewrite /(.*) login/wubo break; }
spec:
#tls:
#- hosts:
# secretName: ding-ingress-secret
rules:
- host: ingress.jettech.com
http:
paths:
- path: /login
backend:
serviceName: jenkins
servicePort: 80(要和port端口一致,port是集群内部服务器之间访问的端口)
- path: /
backend:
serviceName: kubernetes-dashboard
servicePort: 80
- host: ingress.tomcat.com
http:
paths:
- path: /
backend:
serviceName: tomcat
servicePort: 8080
service-nodeport.yaml 这个是对 nginx-ingress-controller做个对外服务统一访问 #对外提供服务,如果不需要可以不下载
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: kube-system
labels:
k8s-app: nginx-ingress-controller
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
nodePort: 32080
- name: https
port: 443
targetPort: 443
protocol: TCP
nodePort: 32443
selector:
k8s-app: nginx-ingress-controller
---
此时有可以通过ingress.jettech.com:32080进行访问,也可以直接ingress.jettech.com访问(直接访问就是没有走service-nodeport.yaml 统一入口)
参考
kubernetes学习笔记之七: Ingress-nginx 部署使用 - 百衲本 - 博客园
Kubernetes学习之路(十五)之Ingress和Ingress Controller - 烟雨浮华 - 博客园
5.2.4总结
从前面的部署过程中,可以再次进行总结部署的流程如下:
①下载Ingress-controller相关的YAML文件,并给Ingress-controller创建独立的名称空间;
②部署后端的服务,如myapp,并通过service进行暴露;
③部署Ingress-controller的service,以实现接入集群外部流量;
④部署Ingress,进行定义规则,使Ingress-controller和后端服务的Pod组进行关联。
本次部署后的说明图如下:
5.2.5 构建TLS站点
(1)准备证书
[root@k8s-master ingress]# openssl genrsa -out tls.key 2048
Generating RSA private key, 2048 bit long modulus
.......+++
.......................+++
e is 65537 (0x10001)
[root@k8s-master ingress]# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=ingress.tomcat.com #注意域名要和服务的域名一致
(2)生成secret
[root@k8s-master ingress]# kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key -n kube-system
secret/tomcat-ingress-secret created
[root@k8s-master-118 ~]# kubectl get secret -n kube-system
NAME TYPE DATA AGE
tomcat-ingress-secret kubernetes.io/tls 2 5m
[root@k8s-master-118 ~]# kubectl describe secret -n kube-system
Name: tomcat-ingress-secret
Namespace: kube-system
Labels: <none>
Annotations: <none>
Type: kubernetes.io/tls
Data
====
tls.crt: 1298 bytes
tls.key: 1679 bytes
(3)创建ingress
cat jenkins-ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: jenkins-ingress
#namespace: default
namespace: kube-system
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
#nginx.ingress.kubernetes.io/configuration-snippet: |
#rewrite /(wubo*) login/wubo break;
#if ($request_uri = '/?%login') { rewrite /(.*) login/wubo break; }
spec:
tls:
- hosts:
- ingress.tomcat.com #与secret证书的域名需要保持一致,也要和下面的-host 保持一致 三致一致
secretName: tomcat-ingress-secret #secret证书的名称
rules:
- host: ingress.jettech.com
http:
paths:
- path: /login
backend:
serviceName: jenkins
servicePort: 80
- path: /
backend:
serviceName: kubernetes-dashboard
servicePort: 80
- host: ingress.tomcat.com
http:
paths:
- path: /
backend:
serviceName: tomcat
servicePort: 8080
https://ingress.tomcat.com:32443
参考Kubernetes学习之路(十五)之Ingress和Ingress Controller - 烟雨浮华 - 博客园
ingress-nginx/index.md at nginx-0.20.0 · kubernetes/ingress-nginx · GitHub
更多推荐
所有评论(0)