k8s中的三种IP

  • Node IP:Node节点的IP地址
  • Pod IP: Pod的IP地址
  • Cluster IP: Service的IP地址

Node IP是Kubernetes集群中节点的物理网卡IP地址(一般为内网),所有属于这个网络的服务器之间都可以直接通信,所以Kubernetes集群外要想访问Kubernetes集群内部的某个节点或者服务,肯定得通过Node IP进行通信(这个时候一般是通过外网IP了)

Pod IP是每个Pod的IP地址,它是Docker Engine根据docker0网桥的IP地址段进行分配的(我们这里使用的是flannel这种网络插件保证所有节点的Pod IP不会冲突)

Cluster IP是一个虚拟的IP,仅仅作用于Kubernetes Service这个对象,由Kubernetes自己来进行管理和分配地址,当然我们也无法ping这个地址,他没有一个真正的实体对象来响应,他只能结合Service Port来组成一个可以通信的服务。

定义Service

例如,假定我们有一组Pod服务的端口为80,它们对外暴露了 8080 端口,同时都被打上了app=myapp这样的标签,那么我们就可以像下面这样来定义一个Service对象:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: myservice
  5. spec:
  6. selector:
  7. app: myapp
  8. ports:
  9. - protocol: TCP
  10. port: 80
  11. targetPort: 8080
  12. name: myapp-http

然后通过的使用kubectl create -f myservice.yaml就可以创建一个名为myservice的Service对象,它会将请求代理到使用 TCP 端口为 8080,具有标签app=myapp的Pod上,这个Service会被系统分配一个我们上面说的Cluster IP,该Service还会持续的监听selector下面的Pod,会把这些Pod信息更新到一个名为myservice的Endpoints对象上去,这个对象就类似于我们上面说的Pod集合了。

Service的类型

定义Service的时候可以指定一个自己需要的类型的Service,如果不指定的话默认是ClusterIP类型。
我们可以使用的服务类型如下:

  • ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的ServiceType。
  • NodePort:通过每个 Node 节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务。
  • LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。
  • ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。

NodePort 类型

如果设置 type 的值为 “NodePort”,Kubernetes master 将从给定的配置范围内(默认:30000-32767)分配端口,每个 Node 将从该端口(每个 Node 上的同一端口)代理到 Service。该端口将通过 Service 的 spec.ports[*].nodePort 字段被指定,如果不指定的话会自动生成一个端口。
需要注意的是,Service 将能够通过 :spec.ports[].nodePort 和 spec.clusterIp:spec.ports[].port 而对外可见。

例如创建一个NodePort的服务来访问我们前面的Nginx服务:(保存为service-demo.yaml)

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: myservice
  5. spec:
  6. selector:
  7. app: myapp
  8. type: NodePort
  9. ports:
  10. - protocol: TCP
  11. port: 80
  12. targetPort: 80
  13. name: myapp-http

ConfigMap

ConfigMap是一个资源对象,许多应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息,这些配置信息我们肯定不会直接写死到应用程序中去的,比如你一个应用连接一个redis服务,下一次想更换一个了的,还得重新去修改代码,重新制作一个镜像,这肯定是不可取的,而ConfigMap就给我们提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,也可以用来保存整个配置文件,比如我们可以用来配置一个redis服务的访问地址,也可以用来保存整个redis的配置文件。

ConfigMap 资源对象使用key-value形式的键值对来配置数据,这些数据可以在Pod里面使用,ConfigMap和Secrets比较类似,一个比较大的区别是ConfigMap可以比较方便的处理一些非敏感的数据,比如密码之类的还是需要使用Secrets来进行管理。

例1、通过文件目录来创建configmap

  1. kubectl create configmap cm-demo1 --from-file=testcm

例2、通过指定文件来创建configmap

  1. kubectl create configmap cm-demo2 --from-file=testcm/redis.conf

ConfigMap的使用

1、使用ConfigMap来填充我们的环境变量:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: testcm1-pod
  5. spec:
  6. containers:
  7. - name: testcm1
  8. image: busybox
  9. command: [ "/bin/sh", "-c", "env" ]
  10. env:
  11. - name: DB_HOST
  12. valueFrom:
  13. configMapKeyRef:
  14. name: cm-demo3
  15. key: db.host
  16. - name: DB_PORT
  17. valueFrom:
  18. configMapKeyRef:
  19. name: cm-demo3
  20. key: db.port
  21. envFrom:
  22. - configMapRef:
  23. name: cm-demo1

Secret 与 ConfigMap 对比

最后我们来对比下SecretConfigMap这两种资源对象的异同点:
相同点:

  • key/value的形式
  • 属于某个特定的namespace
  • 可以导出到环境变量
  • 可以通过目录/文件形式挂载
  • 通过 volume 挂载的配置信息均可热更新

不同点:

  • Secret 可以被 ServerAccount 关联
  • Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像
  • Secret 支持 Base64 加密
  • Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三种类型,而 Configmap 不区分类型