k8s集群安装学习笔记四——Server部分

简介:

Service 的概念
ipvs 代理模式
ClusterIP
Headless Service
NodePort
LoadBalancer
ExternalName
Service-Ingress

Service 的概念

Kubernetes  Service 定义了这样一种抽象:一个Pod 的逻辑分组,一种可以访问它们的策略 ——通常称为微
服务。 这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector

 

Service能够提供负载均衡的能力,但是在使用上有以下限制:
 只提供 4 层负载均衡能力,而没有 7 层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的 。

 

Service 的类型
Service 在 K8s 中有以下四种类型:
1.ClusterIp:默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP。
2.NodePort:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 : <NodeIp>:NodePort 来访问该服务 。
3.LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到: <NodeIp>:NodePort 。
4.ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持 。

 
VIP 和 Service 代理
在 Kubernetes 集群中,每个 Node 运行一个kube-proxy 进程。 kube-proxy 负责为 Service 实现了一种VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。
在 Kubernetes v1.0 版本,代理完全在 userspace。
在Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。
从 Kubernetes v1.2 起,默认就是iptables 代理。 在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理
在 Kubernetes 1.14 版本开始默认使用 ipvs 代理
在 Kubernetes v1.0 版本, Service 是 “4层”(TCP/UDP over IP)概念。
在 Kubernetes v1.1 版本,新增了Ingress API(beta 版),用来表示 “7层”(HTTP)服务 
 
代理模式的分类 
Ⅰ、userspace 代理模式

 

Ⅱ、iptables 代理模式

 

Ⅲ、ipvs 代理模式 
这种模式,kube-proxy 会监视 Kubernetes Service 对象和 Endpoints ,
调用 netlink 接口以相应地创建ipvs 规则并定期与 Kubernetes Service 对象和 Endpoints 对象同步 ipvs 规则,
以确保 ipvs 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod与 iptables 类似,ipvs 于 netfilter 的 hook 功能,
但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。
此外,ipvs 为负载均衡算法提供了更多选项,例如:
rr:轮询调度
lc:最小连接数
dh:目标哈希
sh:源哈希
sed :最短期望延迟
nq : 不排队调度 
 
注意:ipvs模式假定在运行kube-proxy之前在节点上都已经安装了IPVS内核模块。当kube-proxy以ipvs代理模式启动时,
kube-proxy将验证节点上是否安装了IPVS模块,如果未安装,则kube-proxy将回退到iptables代理模式。
 
 
ClusterIP
clusterIP 主要在每个 node 节点使用 iptables/ipvs,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。然
后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个 service 下对应 pod 的地址和端口,进而把
数据转发给对应的 pod 的地址和端口。

 

为了实现图上的功能,主要需要以下几个组件的协同工作:
1.apiserver 用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储到etcd中。
2.kube-proxy kubernetes的每个节点中都有一个叫做kube-porxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables/ipvs规则中。
3.iptables 使用NAT等技术将virtualIP的流量转至endpoint中 。

 

先创建 myapp-deployment.yaml 文件
[root@master manifests]# vim myapp-deployment.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: myapp-deploy 
  namespace: default 
spec: 
  replicas: 3 
  selector: 
    matchLabels: #匹配(app=myapp并且release=stabel的即可)
      app: myapp 
      release: stabel 
  template: 
    metadata: 
      labels: 
        app: myapp 
        release: stabel 
        env: test 
    spec: 
      containers: 
      - name: myapp
        image: wangyanglinux/myapp:v2 
        imagePullPolicy: IfNotPresent 
        ports: 
        - name: http 
          containerPort: 80
kubectl apply -f myapp-deployment.yaml

 

 
创建 Service 信息
[root@master manifests]# vim myapp-service.yaml 
apiVersion: v1 
kind: Service 
metadata: 
  name: myapp 
  namespace: default 
spec: 
  type: ClusterIP 
  selector: #匹配到的标签的pod才能通过svc访问到
    app: myapp 
    release: stabel 
  ports: 
  - name: http 
    port: 80 
    targetPort: 80
 创建svc
kubectl apply -f myapp-service.yaml

 当然也可以直接通过yaml文件的方式直接删除资源

kubectl delete -f myapp-service.yaml

 

创建后就可以通过svc的方式访问三个pod资源了
查看svc信息

 

查看ipvs负载信息

ipvsadm -Ln

 

 

查看pod详细信息

 

访问svc(轮询访问)

 
Headless Service
有时不需要或不想要负载均衡,以及单独的 Service IP 。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP) 的值为 “None” 来创建 Headless Service 。
这类 Service 并不会分配 Cluster IP, kube-proxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由 。
  • 主要的特点是通过无头服务的方式去解决hostname和portname的变化问题,也就是通过它去进行绑定。
[root@k8s-master mainfests]# vim myapp-svc-headless.yaml 
apiVersion: v1 kind: Service metadata: name: myapp
-headless namespace: default spec: selector: app: myapp clusterIP: "None" ports: - port: 80 targetPort: 80
kubectl apply -f myapp-svc-headless.yaml

 

 

 获取当前dns的地址信息

 

 

安装dig命令

yum -y install bind-utils

 

添加A记录域名解析

[root@k8s-master mainfests]# dig -t A myapp-headless.default.svc.cluster.local. @10.96.0.7

 

 

查看网络

 

 虽然None服务无法通过svc访问,但是还是可以通过域名访问至上面这几个不同的pod。域名为:myapp-headless.default.svc.cluster.local

 

NodePort
nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod 。
NodePort的原理是,Kubernetes会在每一个Node上暴露出一个端口:nodePort,外部网络可以通过(任一Node)[NodeIP]:[NodePort]访问到后端的Service
[root@master manifests]# vim nodeport.yaml 
apiVersion: v1 
kind: Service 
metadata: 
  name: myapp 
  namespace: default 
spec: 
  type: NodePort 
  selector: 
    app: myapp 
    release: stabel 
  ports: 
  - name: http 
    port: 80           #和clusterIP对应,即ip:8080,供内部访问
    targetPort: 80     #端口一定要和container暴露出来的端口对应
    nodePort: 32143    #所有的节点都会开放此端口,此端口供外部调用

 

 

 

查看服务器相应端口

 

 

外部访问:

Node服务器IP:30715  即可 (所有node服务器都可这样访问到)

 

查询流程 (如果是IPVS的话使用ipvsadm -Ln查看)
iptables -t nat -nvL KUBE-NODEPORTS

 

 

LoadBalancer
loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用cloud provider(例:阿里云服务搭建的k8s使用SLB) 去创建 LB 来向节点导流。
 

 

ExternalName(可以简单理解为:做了一个dns的别名操作)----好像有些问题
这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:hub.atguigu.com )。
ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和Endpoint。
相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。
 
$ vim ex.yaml
kind: Service apiVersion: v1 metadata: name: my
-service-1 namespace: default spec: type: ExternalName externalName: hub.atguigu.com #公网上可用的域名

$ kubectl create -f ex.yaml

 

 添加A记录解析(会发现多了一个别名)

外部访问hub.atguigu.com即可访问集群内部的pod服务。

 

当查询主机 my-service-1.defalut.svc.cluster.local ( SVC_NAME.NAMESPACE.svc.cluster.local )时,集群的DNS 服务将返回一个值 my.database.example.com 的 CNAME 记录。
访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发 。

 

Service Ingress(最常用)

Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
 

原理及组成部分

Ingress可以理解为Service的Service。它由两部分组成

1.Ingress Controller

  • 这是一个标准,可以有很多实现,其中ingress-nginx是最常用的
  • 以pod形式运行的

2.Ingress策略设置

  • 以yaml形式为载体的一组声明式的策略
  • ingress-controller会动态地按照策略生成配置文件(如:nginx.conf)
 
 
概述:

k8s 对外暴露服务(service)主要有两种方式:NotePort, LoadBalance, 此外externalIPs也可以使各类service对外提供服务,但是当集群服务很多的时候,NodePort方式最大的缺点是会占用很多集群机器的端口;LB方式最大的缺点则是每个service一个LB又有点浪费和麻烦,并且需要k8s之外的支持; 而ingress则只需要一个NodePort或者一个LB就可以满足所有service对外服务的需求。工作机制大致可以用下图表示:

实际上,Ingress相当于一个7层的负载均衡器,是k8s对反向代理的一个抽象。大概的工作原理也确实类似于Nginx,可以理解成在 Ingress 里建立一个个映射规则 , ingress Controller 通过监听 Ingress这个api对象里的配置规则并转化成 Nginx 的配置(kubernetes声明式API和控制循环) , 然后对外部提供服务。

 

部署 Ingress-Nginx
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/aws/deploy-tls-termination.yaml
kubectl apply -f deploy-tls-termination.yaml

部署后包括deployment,svc等都需要创建完成

或者直接访问官网查看部署方式

 

查看创建后暴露的服务地址

kubectl get svc -n ingress-nginx

如果想要访问80端口,就对应31345端口;如果想访问443端口,对应的就是31802端口

 

实验一:

Ingress HTTP 代理访问
deployment、Service、Ingress Yaml 文件,并都通过kubectl apply -f xxx.yaml创建
apiVersion: extensions/v1beta1
kind: Deployment 
metadata: 
  name: nginx-dm 
spec: 
  replicas: 2 
  template: 
    metadata: 
      labels: 
        name: nginx 
    spec: 
      containers: 
      - name: nginx 
        image: wangyanglinux/myapp:v1 
        imagePullPolicy: IfNotPresent 
        ports: 
        - containerPort: 80

 

apiVersion: v1 
kind: Service 
metadata: 
  name: nginx-svc 
spec: 
  ports: 
  - port: 80 
    targetPort: 80 
    protocol: TCP 
  selector: 
    name: nginx #当name=nginx时匹配

 

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: nginx-test 
spec: 
  rules: 
  - host: www1.atguigu.com  #公网域名
    http: 
      paths: 
      - path: / 
        backend: 
          serviceName: nginx-svc  #svc名
          servicePort: 80

#可以看出,这个ingress连接的是svc的名称。

然后就可以通过ingress的域名从外网访问了,注意:访问的端口是上面ingress的端口:31345

 

 

实验二:

根据不同域名实现虚拟主机访问

 实验拓扑图:

 

$ mkdir ingress-vh
$ cd ingress-vh

 

创建第一个deployment和svc

$ vim deployment1.yaml
apiVersion: extensions/v1beta1
kind: Deployment 
metadata: 
  name: deployment1 
spec: 
  replicas: 2 
  template: 
    metadata: 
      labels: 
        name: nginx1
    spec: 
      containers: 
      - name: nginx1
        image: wangyanglinux/myapp:v1 
        imagePullPolicy: IfNotPresent 
        ports: 
        - containerPort: 80

---
apiVersion: v1 
kind: Service 
metadata: 
  name: svc-1 
spec: 
  ports: 
  - port: 80 
    targetPort: 80 
    protocol: TCP 
  selector: 
    name: nginx1 #当name=nginx1时匹配

$ kubectl apply -f deployment1.yaml

测试创建的svc能否访问

 

 

创建第二个deployment和svc

$ vim deployment2.yaml
apiVersion: extensions/v1beta1
kind: Deployment 
metadata: 
  name: deployment2 
spec: 
  replicas: 2 
  template: 
    metadata: 
      labels: 
        name: nginx2 
    spec: 
      containers: 
      - name: nginx2 
        image: wangyanglinux/myapp:v2 
        imagePullPolicy: IfNotPresent 
        ports: 
        - containerPort: 80

---
apiVersion: v1 
kind: Service 
metadata: 
  name: svc-2 
spec: 
  ports: 
  - port: 80 
    targetPort: 80 
    protocol: TCP 
  selector: 
    name: nginx2 #当name=nginx2时匹配

$ kubectl apply -f deployment2.yaml

 

测试svc访问

 

创建ingress

$ vim ingress-rule.yaml

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: ingress1
spec: 
  rules: 
  - host: www1.atguigu.com 
    http: 
      paths: 
      - path: / 
        backend: 
          serviceName: svc-1  #匹配的svc名
          servicePort: 80

---

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: ingress2
spec: 
  rules: 
  - host: www2.atguigu.com 
    http: 
      paths: 
      - path: / 
        backend: 
          serviceName: svc-2  #匹配的svc名
          servicePort: 80

$ kubectl apply -f
ingress-rule.yaml

然后就可以通过两个不同的域名访问不同的资源了 

 

可以进入容器查看ingress生成的nginx配置文件

 kubectl exec pod名称 -n 名称空间 -- /bin/bash

cat nginx.conf

 

 可以看到自动生成的对应域名的配置及反向代理(上面写的ingress规则,会将其转换成nginx的配置文件)

 

访问测试

查看ingress暴露的端口

 网页端访问

 

 查看当前ingress规则

kubectl get ingress

 

 

Ingress HTTPS 代理访问
创建证书,以及 cert 存储方式(使用指定的key创建名为tls-secret的TLS secret)
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" 

kubectl create secret tls tls-secret --key tls.key --cert tls.crt
# tls.crt:公钥 tls.key:私钥 公共密钥证书必须是.PEM编码并匹配指定的私钥

 

deployment、Service、Ingress Yaml 文件
$ vim deployment3.yaml
apiVersion: extensions/v1beta1
kind: Deployment 
metadata: 
  name: deployment3 
spec: 
  replicas: 2 
  template: 
    metadata: 
      labels: 
        name: nginx3 
    spec: 
      containers: 
      - name: nginx3 
        image: wangyanglinux/myapp:v3 
        imagePullPolicy: IfNotPresent 
        ports: 
        - containerPort: 80

---
apiVersion: v1 
kind: Service 
metadata: 
  name: svc-3 
spec: 
  ports: 
  - port: 80 
    targetPort: 80 
    protocol: TCP 
  selector: 
    name: nginx3 #当name=nginx3时匹配

$ kubectl apply -f deployment3.yaml

查看并测试创建结果:

 

$ vim https_ingress.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: https spec: tls: - hosts: - www3.atguigu.com secretName: tls-secret #上面创建时保存的证书名称 rules: - host: www3.atguigu.com http: paths: - path: / backend: serviceName: svc-3 servicePort: 80

$ kubectl apply -f https_ingress.yaml

 

查看当前ingress访问端口

 

 连接测试

 

 

Nginx 进行 BasicAuth (基础认证)
yum -y install httpd 
mkdir basic-auth
cd basic-auth/
htpasswd -c auth foo  #创建秘钥文件为auth,用户名为foo
kubectl create secret generic basic-auth --from-file=auth

 

创建ingress

$ vim ingress.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-with-auth annotations: nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-auth nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo' #说明 spec: rules: - host: auth.atguigu.com #绑定域名 http: paths: - path: / backend: serviceName: svc-1 #链接的svc servicePort: 80

$ kubectl apply -f ingress.yaml

 

访问测试

 

 

 

 

Nginx 进行重写

 

$ vim re.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-test annotations: nginx.ingress.kubernetes.io/rewrite-target: https://www3.atguigu.com:31802 #跳转地址 spec: rules: - host: re.atguigu.com #访问地址 http: paths: - path: / backend: serviceName: svc-1 #这个可以随便链接都行,甚至不链接也可以,因为它没有一个真实主机的存在 ,访问时就会跳转到另一个主机上了 servicePort: 80

$ kubectl apply -f re.yaml

 

访问测试:(可以看到请求re.atguigu.com时跳转到www3.atguigu.com)

 

posted @ 2021-09-15 15:39  叮伱格斐呃  阅读(310)  评论(0编辑  收藏  举报
Live2D