kubernetes 服务主要是指 service 和 ingress
一、作用
- Service是kubernetes 的核心概念,通过创建service,可以为一组具有相同功能的容器应用提供统一的入口地址,并将请求负载分发到后端的各个容器上。
- Ingress 是对service的更高层次的抽象,service是工作在tcp/ip层,基于ip和port的,那么ingress是针对http 7层路由机制,将客户端的请求直接转发到service对应的后端pod服务上。
二、service 类型
service 类型,指定了service的访问方式,默认是clusterIP。
- ClusterIp: 虚拟的服务ip地址,该地址用于Kubernetes集群内部的Pod访问,在Node上Kube-proxy通过设置iptables规则进行转发。
- NodePort:使用宿主机的端口,是能够访问个Node的外部客户,通过Node的IP地址和端口号访问Pod服务。
- LoadBalance:使用外接负载均衡服务器完成到服务器的负载分发,需要在spec.status.loadBalance字段指定外部负载均衡器的IP地址,并同时定义nodeport和clusterIP,用于公有云环境,
三、策略配置
1.service
session affinity:能够将来自同一个客户端的请求始终转发至同一个后端POD,其会降低负载均衡的效果。
端口协议:支持TCP和UDP,默认TCP。
targetPort: 需要转发到的后端pod端口号。
nodePort: 指定映射到物理机的端口号。
多端口service:一个容器也可以提供多个端口服务,那么在service的定义中也可以相应的设置为多个端口对应的多端口应用服务。
Headless Service: 不为service设置clusterIP,通过Label Selectot将后端的Pod列表返回给客户端,开发人员自己控制负载均衡策略,不使用service提供的默认负载均衡策略。clusterIP字段设置为node。
DNS: DNS 服务的搭建和配置(这里不做详细解释)。
2.ingress
- 转发到单个后端服务上,Ingress无需定义任何rule
- 同一域名下,不同的URL路径被转发到不同的服务上
- 不同域名(虚拟主机名),转发到不同的服务上
- 不使用域名的转发规则
- Ingrss 的TLS安全设置,需secret资源配置使用 (安全机制详细解释)
注意:使用无域名的Ingress转发规则时,将默认禁用非安全HTTP,强制启动HTTPS。
四、clinet-go 实现service 管理
1. service 相关api 接口
client-go/kubernetes/typed/core/v1/service.go
// ServiceInterface has methods to work with Service resources.
type ServiceInterface interface {
Create(*v1.Service) (*v1.Service, error)
Update(*v1.Service) (*v1.Service, error)
UpdateStatus(*v1.Service) (*v1.Service, error)
Delete(name string, options *metav1.DeleteOptions) error
Get(name string, options metav1.GetOptions) (*v1.Service, error)
List(opts metav1.ListOptions) (*v1.ServiceList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error)
ServiceExpansion
}
上面描述了service相关所有接口,包括Create(),Update(),updateStatus(),Delete(),DeleteCollection(),Get(),List(),Watch(),Patch()。
2. service request 结构
k8s.io/api/core/v1/types.go
// Service is a named abstraction of software service (for example, mysql) consisting of local port
// (for example 3306) that the proxy listens on, and the selector that determines which pods
// will answer requests sent through the proxy.
type Service struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the behavior of a service.
// https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
Spec ServiceSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Most recently observed status of the service.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
Status ServiceStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// ServiceSpec describes the attributes that a user creates on a service.
type ServiceSpec struct {
// The list of ports that are exposed by this service.
// More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
// +patchMergeKey=port
// +patchStrategy=merge
// +listType=map
// +listMapKey=port
// +listMapKey=protocol
Ports []ServicePort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"port" protobuf:"bytes,1,rep,name=ports"`
// Route service traffic to pods with label keys and values matching this
// selector. If empty or not present, the service is assumed to have an
// external process managing its endpoints, which Kubernetes will not
// modify. Only applies to types ClusterIP, NodePort, and LoadBalancer.
// Ignored if type is ExternalName.
// More info: https://kubernetes.io/docs/concepts/services-networking/service/
// +optional
Selector map[string]string `json:"selector,omitempty" protobuf:"bytes,2,rep,name=selector"`
// clusterIP is the IP address of the service and is usually assigned
// randomly by the master. If an address is specified manually and is not in
// use by others, it will be allocated to the service; otherwise, creation
// of the service will fail. This field can not be changed through updates.
// Valid values are "None", empty string (""), or a valid IP address. "None"
// can be specified for headless services when proxying is not required.
// Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if
// type is ExternalName.
// More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
// +optional
ClusterIP string `json:"clusterIP,omitempty" protobuf:"bytes,3,opt,name=clusterIP"`
// type determines how the Service is exposed. Defaults to ClusterIP. Valid
// options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
// "ExternalName" maps to the specified externalName.
// "ClusterIP" allocates a cluster-internal IP address for load-balancing to
// endpoints. Endpoints are determined by the selector or if that is not
// specified, by manual construction of an Endpoints object. If clusterIP is
// "None", no virtual IP is allocated and the endpoints are published as a
// set of endpoints rather than a stable IP.
// "NodePort" builds on ClusterIP and allocates a port on every node which
// routes to the clusterIP.
// "LoadBalancer" builds on NodePort and creates an
// external load-balancer (if supported in the current cloud) which routes
// to the clusterIP.
// More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
// +optional
Type ServiceType `json:"type,omitempty" protobuf:"bytes,4,opt,name=type,casttype=ServiceType"`
// externalIPs is a list of IP addresses for which nodes in the cluster
// will also accept traffic for this service. These IPs are not managed by
// Kubernetes. The user is responsible for ensuring that traffic arrives
// at a node with this IP. A common example is external load-balancers
// that are not part of the Kubernetes system.
// +optional
ExternalIPs []string `json:"externalIPs,omitempty" protobuf:"bytes,5,rep,name=externalIPs"`
// Supports "ClientIP" and "None". Used to maintain session affinity.
// Enable client IP based session affinity.
// Must be ClientIP or None.
// Defaults to None.
// More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
// +optional
SessionAffinity ServiceAffinity `json:"sessionAffinity,omitempty" protobuf:"bytes,7,opt,name=sessionAffinity,casttype=ServiceAffinity"`
// Only applies to Service Type: LoadBalancer
// LoadBalancer will get created with the IP specified in this field.
// This feature depends on whether the underlying cloud-provider supports specifying
// the loadBalancerIP when a load balancer is created.
// This field will be ignored if the cloud-provider does not support the feature.
// +optional
LoadBalancerIP string `json:"loadBalancerIP,omitempty" protobuf:"bytes,8,opt,name=loadBalancerIP"`
// If specified and supported by the platform, this will restrict traffic through the cloud-provider
// load-balancer will be restricted to the specified client IPs. This field will be ignored if the
// cloud-provider does not support the feature."
// More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/
// +optional
LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty" protobuf:"bytes,9,opt,name=loadBalancerSourceRanges"`
// externalName is the external reference that kubedns or equivalent will
// return as a CNAME record for this service. No proxying will be involved.
// Must be a valid RFC-1123 hostname (https://tools.ietf.org/html/rfc1123)
// and requires Type to be ExternalName.
// +optional
ExternalName string `json:"externalName,omitempty" protobuf:"bytes,10,opt,name=externalName"`
// externalTrafficPolicy denotes if this Service desires to route external
// traffic to node-local or cluster-wide endpoints. "Local" preserves the
// client source IP and avoids a second hop for LoadBalancer and Nodeport
// type services, but risks potentially imbalanced traffic spreading.
// "Cluster" obscures the client source IP and may cause a second hop to
// another node, but should have good overall load-spreading.
// +optional
ExternalTrafficPolicy ServiceExternalTrafficPolicyType `json:"externalTrafficPolicy,omitempty" protobuf:"bytes,11,opt,name=externalTrafficPolicy"`
// healthCheckNodePort specifies the healthcheck nodePort for the service.
// If not specified, HealthCheckNodePort is created by the service api
// backend with the allocated nodePort. Will use user-specified nodePort value
// if specified by the client. Only effects when Type is set to LoadBalancer
// and ExternalTrafficPolicy is set to Local.
// +optional
HealthCheckNodePort int32 `json:"healthCheckNodePort,omitempty" protobuf:"bytes,12,opt,name=healthCheckNodePort"`
// publishNotReadyAddresses, when set to true, indicates that DNS implementations
// must publish the notReadyAddresses of subsets for the Endpoints associated with
// the Service. The default value is false.
// The primary use case for setting this field is to use a StatefulSet's Headless Service
// to propagate SRV records for its Pods without respect to their readiness for purpose
// of peer discovery.
// +optional
PublishNotReadyAddresses bool `json:"publishNotReadyAddresses,omitempty" protobuf:"varint,13,opt,name=publishNotReadyAddresses"`
// sessionAffinityConfig contains the configurations of session affinity.
// +optional
SessionAffinityConfig *SessionAffinityConfig `json:"sessionAffinityConfig,omitempty" protobuf:"bytes,14,opt,name=sessionAffinityConfig"`
}
其实上述结构信息,就是通命令行创建(kubectl apply -f yaml)service时,yaml 描述文件里的信息。
3. 向 apiserver 发送请求,对service 进行操作
3.1 create
_, err := cli.CoreV1().Services(service.Namespace).Create(&service)
if err != nil {
panic(err.Error())
}
3.2 update
newservice, err := cli.CoreV1().Services(service.Namespace).Update(&service);
if err != nil{
panic(err.Error())
}
newservice 为update 后的service结构信息
3.3 get
service, err := cli.CoreV1().Services(service.Namespace).Get(service.Name, metaV1.GetOptions{})
if err != nil {
panic(err.Error())
}
3.3 delete
err = cli.CoreV1().Services(namespace).Delete(name, &metaV1.DeleteOptions{})
if err != nil {
panic(err.Error())
}
通过以上几个接口,就可以基本完成对Service的管理了。
五、clinet-go 实现ingress管理
clinet-go 对ingress 的操作接口跟service类似,只是配置策略部分不同,相关操作参考service。