My Kubernetes cluster is running under Google Cloud. I have deployment which running with port 443 and LoadBalancer expose it to the internet.
I created it in this way:
kubectl expose deployment my-app --target-port=443 --port=443 --type=LoadBalancer
After running this command, the loadbalancer is pointing to my-app
deployment. Now I created my-app2
and I want to change the loadbalancer to point the new deployment (my-app2
).
Note: Delete and re-create the deployment is releasing the external IP address and I want to avoid it.
How to patch the existing service to point another deployment without loosing the external IP?
Finally, found the solution:
kubectl patch service old-app -p '{"spec":{"selector":{"app": "new-app"}}}'
This is covered in the tutorial for GKE here.
Firstly, you should reserve a static IP address, so that it is re-used between deployments.
You can do this in the GCP console or via the command, like so: gcloud compute addresses create helloweb-ip --region us-central1
Then you can find the static IP address you have been allocated: gcloud compute addresses describe helloweb-ip --region us-central1
Then you should use this IP address when setting up your LoadBalancer
service. In "imperative" commands, you would type:
kubectl expose deployment my-app --target-port=443 --port=443 --type=LoadBalancer --loadBalancerIP=YOUR.IP.ADDRESS.HERE
The YAML "declarative" form is convenient as the setup gets more complex, this can also saved for re-use in future. For example:
apiVersion: v1
kind: Service
metadata:
name: helloweb
labels:
app: hello
spec:
selector:
app: hello
tier: web
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
loadBalancerIP: "YOUR.IP.ADDRESS.HERE"
Yes, you can use already existing service to point new deployment.
All you've to do, edit the service YAML with newly deployed service's label.
Suppose, you've newly deployed services yaml as below.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: my-app-2
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
It has label as
template:
metadata:
labels:
app: my-app-2
If your service is as below:
kind: Service
apiVersion: v1
metadata:
name: my-app
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 80
you only need to change selector section of service
selector:
app: my-app
to
selector:
app: my-app-2