Introduction to YAML, Part 2: Kubernetes Services, Ingress, and repeated nodes
The post Introduction to YAML, Part 2: Kubernetes Services, Ingress, and repeated nodes appeared first on Mirantis | Pure Play Open Cloud.
In part 1 of this series, we looked at the basics behind YAML and showed you how to create basic Kubernetes objects such as Pods and Deployments using the two basic structures of YAML, Maps and Lists. Now we’re going to look at enhancing your YAML documents with repeated nodes in the context of Kubernetes Services, Endpoints, and Ingress.
Let’s start with a basic scalar value.
A simple repeated scalar value in YAML: building a Kubernetes Service
To see how we can create a simple repeated value, we’re going to look at Kubernetes Services. A complete look at Services is beyond the scope of this article, but there are three basic things you need to understand:
Services are how pods communicate, either with either other or with the outside world. They do this by specifying a port for the caller to use, and a targetPort, which is the port on which the Pod itself receives the message.
Services know which pods to target based on labels specified in the selector.
Services come in four different types:
ClusterIP: The default ServiceType, a ClusterIP service makes the service reachable from within the cluster via a cluster-internal IP.
NodePort: A NodePort service makes it possible to access a Service by directing requests to a specific port on every Node, accessed via the NodeIP. (Kubernetes automatically creates a ClusterIP service to route the request.) So from outside the cluster, you’d send the request to <NodeIP>:<NodePort>.
LoadBalancer: In order to use a LoadBalancer service, you have to be using a cloud provider that supports it; it’s the cloud provider that actually makes this functionality available. This service sits on top of NodePort and ClusterIP services, which Kubernetes creates automatically.
ExternalName: In production situations, you will likely want to use ExternalName, which maps the service to a CNAME record such as a Fully Qualified Domain Name.
OK, with the basics under our belt, let’s take a look at actually creating one.
Repeated values with anchors and aliases
In part 1, we covered the basics of creating Kubernetes objects using YAML, and creating a Service is no different.
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
– port: 80
name: http
targetPort: 80
– port: 443
name: https
targetPort: 80
As you can see, we’re creating an object just as we did in Part 1, with metadata and a spec. Metadata is the same as it was when we were dealing with Deployments, in that we are specifying information about the object and adding labels to any instances created.
As for the spec, a Service needs two basic pieces of information: a selector, which identifies Pods that it should work with (in this case, any pods with the label app=nginx) and the ports the service manages. In this case, we have two external ports, both of which get forwarded to port 80 of the actual pod.
So let’s make this more convenient. We can create an anchor that specifies a value, then use an alias to reference that anchor. For example:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
– port: &target 80
name: http
targetPort: *target
– port: 443
name: https
targetPort: *target
We create the anchor with the ampersand (&), as in &target, then reference it with the alias created with the asterisk (*), as in *target. If we were to put this into a file and create it using kubectl, we would get a new Service, as we can see:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 32d
nginx ClusterIP 10.107.206.48 <none> 80/TCP,443/TCP 13m
If we then went on to describe the service, we could see that the values carried through:
$ kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: app=nginx
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{“apiVersion”:”v1″,”kind”:”Service”,”metadata”:{“annotations”:{},”labels”:{“app”:”nginx”},”name”:”nginx”,”namespace”:”default”},”spec”:{“p…
Selector: app=nginx
Type: ClusterIP
IP: 10.107.206.48
Port: http 80/TCP
TargetPort: 80/TCP
Endpoints: <none>
Port: https 443/TCP
TargetPort: 80/TCP
Endpoints: <none>
Session Affinity: None
Events: <none>
Now if we wanted to change that port, we could do it simply by changing the anchor:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
– port: &target 88
name: http
targetPort: *target
– port: 443
name: https
targetPort: *target
We can then apply the changes…
$ kubectl apply -f test.yaml
service/nginx configured
… and look at the newly configured service:
$ kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: app=nginx
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{“apiVersion”:”v1″,”kind”:”Service”,”metadata”:{“annotations”:{},”labels”:{“app”:”nginx”},”name”:”nginx”,”namespace”:”default”},”spec”:{“p…
Selector: app=nginx
Type: ClusterIP
IP: 10.107.206.48
Port: http 88/TCP
TargetPort: 88/TCP
Endpoints: <none>
Port: https 443/TCP
TargetPort: 88/TCP
Endpoints: <none>
Session Affinity: None
Events: <none>
As you can see, all three values were changed by simply changing the anchor. Handy, but fortunately, we can also create anchors for more complicated structures.
Anchors for non-scalars: Creating Endpoints
Endpoints are, as in other applications, the target to which you’ll send your requests in order to access an application. Kubernetes creates them automatically, but you can also create them manually and link them to a specific service. For example:
apiVersion: v1
kind: Endpoints
metadata:
name: mytest-cluster
subsets:
– addresses:
– ip: 192.168.10.100
ports:
– name: myport
port: 1
protocol: TCP
– addresses:
– ip: 192.168.10.101
ports:
– name: myport
port: 1
protocol: TCP
– addresses:
– ip: 192.168.10.102
ports:
– name: myport
port: 1
protocol: TCP
As you can see, what you have here is the basic structure, only instead of a spec, we have subsets, each of which consists of one or more IP addresses and the ports to access them.
So now let’s look at creating an anchor out of one of those port definitions:
apiVersion: v1
kind: Endpoints
metadata:
name: mytest-cluster
subsets:
– addresses:
– ip: 192.168.10.100
ports: &stdport
– name: myport
port: 1
protocol: TCP
– addresses:
– ip: 192.168.10.101
ports: *stdport
– addresses:
– ip: 192.168.10.102
ports: *stdport
If we describe the endpoints we can see that they’ve been created as we expect:
$ kubectl describe endpoints mytest-cluster
Name: mytest-cluster
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{“apiVersion”:”v1″,”kind”:”Endpoints”,”metadata”:{“annotations”:{},”name”:”mytest-cluster”,”namespace”:”default”},”subsets”:[{“addresses”:…
Subsets:
Addresses: 192.168.10.100,192.168.10.101,192.168.10.102
NotReadyAddresses: <none>
Ports:
Name Port Protocol
—- —- ——–
myport 1 TCP
Events: <none>
But when you’re using an alias for a structure such as this, you’ll often want to change a specific value and leave the rest intact. We’ll do that next.
Changing a specific value: Kubernetes Ingress
In this final section, we’ll look at creating a Kubernetes Ingress, which makes it simpler to create access to your applications. We’ll also look at another aspect of using aliases.
In the previous section we looked at replacing entire objects with an alias, but sometimes you want to do that with slight changes. For example, we might have an Ingress that looks like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
– http:
paths:
– path: /testpath
backend: &stdbe
serviceName: test
servicePort: 80
– path: /realpath
backend: *stdbe
– path: /hiddenpath
backend: *stdbe
In this case, we have three paths that all point to the same service on the same port. But what if we want to have one path that points to another port? To do that we want to override one of the existing values, like so:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
– http:
paths:
– path: /testpath
backend: &stdbe
serviceName: test
servicePort: 80
– path: /realpath
backend: *stdbe
– path: /hiddenpath
backend:
<< : *stdbe
servicePort: 443
Now, a couple of things to note here. First off, the alias represents a value, so it has to have a name. We can’t use backend as the name, because we need *stdbe down one level so that we can replace servicePort. So to reference the fact that we’re going up one level, we’re using the << notation. Then we can add another servicePort value to the same level of the hierarchy.
Now if we go ahead and apply this YAML, we can see the results:
$ kubectl apply -f test.yaml
ingress.extensions/test-ingress configured
$ kubectl describe ingress test-ingress
Name: test-ingress
Namespace: default
Address:
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
—- —- ——–
*
/testpath test:80 (<none>)
/realpath test:80 (<none>)
/hiddenpath test:443 (<none>)
Annotations:
kubectl.kubernetes.io/last-applied-configuration: {“apiVersion”:”extensions/v1beta1″,”kind”:”Ingress”,”metadata”:{“annotations”:{“nginx.ingress.kubernetes.io/rewrite-target”:”/”},”name”:”test-ingress”,”namespace”:”default”},”spec”:{“rules”:[{“http”:{“paths”:[{“backend”:{“serviceName”:”test”,”servicePort”:80},”path”:”/testpath”},{“backend”:{“serviceName”:”test”,”servicePort”:80},”path”:”/realpath”},{“backend”:{“serviceName”:”test”,”servicePort”:443},”path”:”/hiddenpath”}]}}]}}
nginx.ingress.kubernetes.io/rewrite-target: /
Events: <none>
So that’s anchors and aliases. If you want more information on YAML, including using specific data types, feel free to check out this webinar on YAML and Kubernetes objects.
The post Introduction to YAML, Part 2: Kubernetes Services, Ingress, and repeated nodes appeared first on Mirantis | Pure Play Open Cloud.
Quelle: Mirantis