Service types

There are four types of services:

  • ClusterIP
  • NodePort
  • LoadBalancer
  • ExternalName

LoadBalancer includes the features of NodePort and ClusterIP

ClusterIP

ClusterIP is the default service type. It exposes the service on a cluster-internal IP. Pods in the cluster could reach the service via the IP address, environment variables, or DNS.

In the following example, we'll learn how to use both native service environment variables and DNS to access the pods behind services in the cluster.

Before starting a service, we'd like to create two sets of RC shown below

# create RC 1 with nginx 1.12.0 version
cat << EOF > 3-2-3_rc1.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-1.12
spec:
  replicas: 2
  selector:
    project: chapter3
    service: web
    version: "0.1"
  template:
    metadata:
      name: nginx
      labels:
        project: chapter3
        service: web
        version: "0.1"
    spec:
      containers:
      - name: nginx
        image: nginx:1.12.0
        ports:
        - containerPort: 80
EOF

# create RC 2 with nginx 1.13.1 version
cat << EOF > 3-2-3_rc2.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-1.13
spec:
  replicas: 2
  selector:
    project: chapter3
    service: web
    version: "0.2"
  template:
    metadata:
      name: nginx
      labels:
        project: chapter3
        service: web
        version: "0.2"
    spec:
      containers:
      - name: nginx
        image: nginx:1.13.1
        ports:
        - containerPort: 80
EOF

Then we could make our pod selector, targeting project and service labels

# simple nginx service
cat << EOF > 3-2-3_service.yaml
kind: Service
apiVersion: v1
metadata:
  name: nginx-service
spec:
  selector:
    project: chapter3
    service: web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      name: http
EOF
# create the RCs
kubectl create -f 3-2-3_rc1.yaml
replicationcontroller "nginx-1.12" created

kubectl create -f 3-2-3_rc2.yaml
replicationcontroller "nginx-1.13" created

# create the service
kubectl create -f 3-2-3_service.yaml
service "nginx-service" created

Check nginx-service information

kubectl describe service nginx-service

Name:              nginx-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          project=chapter3,service=web
Type:              ClusterIP
IP:                10.43.9.128
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.42.1.3:80,10.42.2.4:80,10.42.3.3:80 + 1 more...
Session Affinity:  None
Events:            <none>

List current endpoints

kubectl get endpoints

NAME            ENDPOINTS                                                                AGE
kubernetes      159.65.144.250:6443,159.65.156.182:6443,159.65.159.71:6443 + 2 more...   1h
nginx           10.42.2.3:80,10.42.3.2:80                                                8m
nginx-service   10.42.1.3:80,10.42.2.4:80,10.42.3.3:80 + 1 more...                       1m
curl 10.42.1.3:80
curl 10.42.2.3:80
curl 10.42.2.4:80
curl 10.42.3.2:80
curl 10.42.3.3:80

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

By default, Kubernetes will expose seven environment variables for each service. In most cases, the first two will be used for using kube-dns addon to do service discovery for us

  1. ${SVCNAME}_SERVICE_HOST
  2. ${SVCNAME}_SERVICE_PORT
  3. ${SVCNAME}_PORT
  4. ${SVCNAME}PORT${PORT}_${PROTOCAL}
  5. ${SVCNAME}PORT${PORT}_${PROTOCAL}_PROTO
  6. ${SVCNAME}PORT${PORT}_${PROTOCAL}_PORT
  7. ${SVCNAME}PORT${PORT}_${PROTOCAL}_ADDR

We'll create a pod called clusterip-chk to access nginx containers via nginx-service

export NGINX_SERVICE_SERVICE_HOST=10.42.1.3

cat << EOF > 3-2-3_clusterip_chk.yaml
apiVersion: v1
kind: Pod
metadata:
  name: clusterip-chk
spec:
  containers:
  - name: centos
    image: centos
    command: ["/bin/sh", "-c", "while : ;do curl http://${NGINX_SERVICE_SERVICE_HOST}:80/; sleep 10; done"]
EOF

kubectl create -f 3-2-3_clusterip_chk.yaml
pod "clusterip-chk" created

Check stdout, see if we can access nginx pod successfully

kubectl logs -f clusterip-chk

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
100   612  100   612    0     0   269k      0 --:--:-- --:--:-- --:--:--  597k

NodePort

If the service is set as NodePort, Kubernetes will allocate a port within a certain range on each node. Any traffic going to nodes on that port will be routed to the service port. Port number could be user-specified. If not specified, Kubernetes will randomly choose a port from range 30000 to 32767 without collision. On the other hand, if specified, the user should be responsible to manage the collision by themselves. NodePort includes the feature of ClusterIP. Kubernetes assigns an internal IP to the service.

cat << EOF > 3-2-3_nodeport.yaml
kind: Service
apiVersion: v1
metadata:
  name: nginx-nodeport
spec:
  type: NodePort
  selector:
    project: chapter3
    service: web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
EOF

kubectl create -f 3-2-3_nodeport.yaml
service "nginx-nodeport" created
kubectl get endpoints
NAME             ENDPOINTS                                                                AGE
kubernetes       159.65.144.250:6443,159.65.156.182:6443,159.65.159.71:6443 + 2 more...   1h
nginx-nodeport   10.42.1.3:80,10.42.2.4:80,10.42.3.3:80 + 1 more...                       1m

curl 10.42.1.3:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
kubectl expose services/nginx-nodeport --type="NodePort" --port 8080

LoadBalancer

This type is only usable with cloud provider support, such as Google Cloud Platform and Amazon Web Service. By creating LoadBalancer service, Kubernetes will provision a load balancer by the Cloud provider to the service.

ExternalName

Sometimes we leverage different services in the cloud. Kubernetes is flexible enough to be hybrid. ExternalName is one of the bridges to create a CNAME for external endpoints into the cluster.

Service without selectors

Service uses selectors to match the pods to direct the traffic. However, sometimes you need to implement a proxy to be the bridge between Kubernetes cluster and another namespace, another cluster, or external resources.

Create a service without selectors

cat << EOF > 3-2-3_service_wo_selector_srv.yaml
kind: Service
apiVersion: v1
metadata:
  name: google-proxy
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
EOF

kubectl create -f 3-2-3_service_wo_selector_srv.yaml
service "google-proxy" created

No Kubernetes endpoint will be created since there is no selector. Kubernetes doesn't know where to route the traffic since no selector could match the pods. We'll have to create that on our own.

In the Endpoints object, the source addresses can't be DNS name, so we'll use nslookup to find the current Google IP from the domain, and add them into Endpoints.subsets.addresses.ip

nslookup www.google.com
Server:         67.207.67.3
Address:        67.207.67.3#53

Non-authoritative answer:
Name:   www.google.com
Address: 172.217.166.132
# create endpoints for the ip from google.com
cat << EOF > 3-2-3_service_wo_selector_endpoints.yaml
kind: Endpoints
apiVersion: v1
metadata:
  name: google-proxy
subsets:
  - addresses:
      - ip: 172.217.166.132
    ports:
      - port: 80
EOF

kubectl create -f 3-2-3_service_wo_selector_endpoints.yaml
endpoints "google-proxy" created

Let's create another pod in the cluster to access our Google proxy

export GOOGLE_PROXY_SERVICE_HOST=172.217.166.132
cat << EOF > 3-2-3_proxy-chk.yaml
apiVersion: v1
kind: Pod
metadata:
  name: proxy-chk
spec:
  containers:
  - name: centos
    image: centos
    command: ["/bin/sh", "-c", "while : ;do curl -L http://${GOOGLE_PROXY_SERVICE_HOST}:80/; sleep 10; done"]
EOF

kubectl create -f 3-2-3_proxy-chk.yaml
pod "proxy-chk" created

Let's check the stdout from the pod

kubectl logs proxy-chk

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   219  100   219    0     0   1937      0 --:--:-- --:--:-- --:--:--  1955
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-IN"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/logos/doodles/2018
/world-cup-2018-day-1-5741876039647232-l.png" itemprop="image"><meta content="World Cup 2018 - Day 1" property="twitter:title"><meta content="Let the matches begin! Celebrate &#9917; around t
he &#127758;&#127757;&#127759; in today's #GoogleDoodle!" property="twitter:description"><meta content="Let the matches begin! Celebrate &#9917; around the &#127758;&#127757;&#127759; in toda
y's #GoogleDoodle!" property="og:description"><meta content="summary_large_image" property="twitter:card"><meta content="@GoogleDoodles" property="twitter:site"><meta content="https://www.goo
gle.com/logos/doodles/2018/world-cup-2018-day-1-5741876039647232-2x.png" property="twitter:image"><meta content="https://www.google.com/logos/doodles/2018/world-cup-2018-day-1-574187603964723
2-2x.png" property="og:image"><meta content="1150" property="og:image:width"><meta content="460" property="og:image:height"><title>Google</title><script nonce="hm4yHsDVv023E+mSwE8/2Q==">(func
tion(){window.google={kEI:'SwgiW7OQFYv4vgSO35_oDA',kEXPI:'0,201836,1151911,57,1957,930,88,39,241,160,336,214,852,48,30,75,566,60,9,89,43,154,321,62,190,2339794,240,187,32,21,329273,1294,12383
,2347,2508,32692,15247,864,772,7,792,7,5117,5471,6381,3335,2,2,2138,2471,2192,367,550,664,2102,113,2201,3191,224,502,5,1711,58,71,131,4628,479,575,1119,2,579,663,64,311,3,298,1820,58,2,2,2,54
2,755,284,1059,369,27,1349,505,730,377,26,1214,479,609,55,630,9,299,237,1032,280,494,194,1038,1021,278,2,694,148,282,1666,35,428,330,28,850,393,132,22,180,419,5,2,2,151,506,443,218,2,78,345,1
67,389,125,2,65,3,613,161,161,5,391,29,272,31,361,505,1151,685,260,214,82,236,60,6,145,195,79,623,205,163,500,11,40,35,57,80,28,334,123,7,483,373,383,105,394,902,182,7,3,25,506,19,381,4,4,108
,83,714,187,4,4,4,4,79,267,2330676,3685998,2545,9,5997613,2800173,4,1572,549,332,445,1,2,1,1,77,1,1,900,207,1,1,1,1,1,366,9,309,1,8,1,2,1,1,924,181,1,19,2,4,18,17,2,17,232,21,11,11,1,1,223104
74',authuser:0,kscs:'c9c918f0_SwgiW7OQFYv4vgSO35_oDA',kGL:'IN'};google.kHL='en-IN';})();google.time=function(){return(new Date).getTime()};(function(){google.lc=[];google.li=0;google.getEI=fu
nction(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute("le
id")));)a=a.parentNode;return b};google.https=function(){return"https:"==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch
(d){}};google.log=function(a,b,d,c,g){if(a=google.logUrl(a,b,d,c,g)){b=new Image;var e=google.lc,f=google.li;e[f]=b;b.onerror=b.onload=b.onabort=function(){delete e[f]};google.vel&&google.vel
.lu&&google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,d,c,g){var e="",f=google.ls||"";d||-1!=b.search("&ei=")||(e="&ei="+google.getEI(c),-1==b.search("&lei=")&&(c=google.ge
tLEI(c))&&(e+="&lei="+c));c="";!d&&google.cshid&&-1==b.search("&cshid=")&&(c="&cshid="+google.cshid);a=d||"/"+(g||"gen_204")+"?atyp=i&ct="+a+"&cad="+b+e+f+"&zx="+google.time()+c;/^http:/i.tes
t(a)&&google.https()&&(google.ml(Error("a"),!1,{src:a,glmm:1}),a="");return a};}).call(this);(function(){google.y={};google.x=function(a,b){if(a)var c=a.id;else{do c=Math.random();while(googl
e.y[c])}google.y[c]=[a,b];return!1};google.lm=[];google.plm=function(a){google.lm.push.apply(google.lm,a)};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=f
unction(a,b){google.lq.push([a,b])};}).call(this);google.f={};var a=window.location,b=a.href.indexOf("#");if(0<=b){var c=a.href.substring(b+1);/(^|&)q=/.test(c)&&-1==c.indexOf("#")&&a.replace
("/search?"+c.replace(/(^|&)fp=[^&]*/g,"")+"&cad=h")};</script><style>#gbar,#guser{font-size:13px;padding-top:1px !important;}#gbar{height:22px}#guser{padding-bottom:7px !important;text-align
:right}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}@media all{.gb1{height:22px;margin-right:.5em;vertical-align:top}#gbar{float:le
ft}}a.gb1,a.gb4{text-decoration:underline !important}a.gb1,a.gb4{color:#00c !important}.gbi .gb4{color:#dd8e27 !important}.gbf .gb4{color:#900 !important}
</style><style>body,td,a,p,.h{font-family:arial,sans-serif}body{margin:0;overflow-y:scroll}#gog{padding:3px 8px 0}td{line-height:.8em}.gac_m td{line-height:17px}form{margin-bottom:20px}.h{col
or:#36c}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}em{font-weight:bold;font-style:normal}.lst{height:25px;width:496px}.gsfi,.lst{font:18px arial,sans-serif}.gsfs{font:17px ar
ial,sans-serif}.ds{display:inline-box;display:inline-block;margin:3px 0 4px;margin-left:4px}input{font-family:inherit}a.gb1,a.gb2,a.gb3,a.gb4{color:#11c !important}body{background:#fff;color:
black}a{color:#11c;text-decoration:none}a:hover,a:active{text-decoration:underline}.fl a{color:#36c}a:visited{color:#551a8b}a.gb1,a.gb4{text-decoration:underline}a.gb3:hover{text-decoration:n
one}#ghead a.gb2:hover{color:#fff !important}.sblc{padding-top:5px}.sblc a{display:block;margin:2px 0;margin-left:13px;font-size:11px}.lsbb{background:#eee;border:solid 1px;border-color:#ccc
#999 #999 #ccc;height:30px}.lsbb{display:block}.ftl,#fll a{display:inline-block;margin:0 12px}.lsb{background:url(/images/nav_logo229.png) 0 -261px repeat-x;border:none;color:#000;cursor:poin
ter;height:30px;margin:0;outline:0;font:15px arial,sans-serif;vertical-align:top}.lsb:active{background:#ccc}.lst:focus{outline:none}</style><script nonce="hm4yHsDVv023E+mSwE8/2Q=="></script>
<link href="/images/branding/product/ico/googleg_lodp.ico" rel="shortcut icon"></head><body bgcolor="#fff"><script nonce="hm4yHsDVv023E+mSwE8/2Q==">(function(){var src='/images/nav_logo229.pn
g';var iesg=false;document.body.onload = function(){window.n && window.n();if (document.images){new Image().src=src;}
if (!iesg){document.f&&document.f.q.focus();document.gbqf&&document.gbqf.q.focus();}
}
  0     0    0 14069    0     0  44889      0 --:--:-- --:--:-- --:--:-- 44889

We can now confirm the proxy works. The traffic to the service will be routed to the endpoints we specified.

results matching ""

    No results matching ""