Update Kubernetes Service Endpoint IP

10/4/2021

I uses a Kubernetes application with a Service that has a single Endpoint. If using curl I retrieve it, I got something like this:

{
  "kind": "Endpoints",
  "apiVersion": "v1",
  "metadata": {
  ...
  "subsets": [
    {
      "addresses": [
        {
          "ip": "172.16.235.204"
        }
      ],
      ...
    }
  ]

Now under given circumstances, my application needs to change its IP with a curl PATCH. I am using the following code:

KUBE_SERVICE_DIR="/var/run/secrets/kubernetes.io/serviceaccount"
KUBE_TOKEN_FILENAME="${KUBE_SERVICE_DIR}/token"
KUBE_CA_CERT="${KUBE_SERVICE_DIR}/ca.crt"
KUBE_TOKEN=$(cat ${KUBE_TOKEN_FILENAME})
BODY='[{"op": "replace", "path": "subsets/0/addresses/0/ip", "value": "172.16.140.18"}]'
curl -XPATCH --cacert ${KUBE_CA_CERT} -H "Content-Type: application/json-patch+json" -H "Authorization: Bearer ${KUBE_TOKEN}" --data "${BODY}" "https://${KUBERNETES_API_HOST}:${KUBERNETES_API_PORT}/api/v1/namespaces/cf-db/endpoints/cfdb-ccdb"

As you can see my patch JSON is trying to apply a replace operation on this path subsets/0/addresses/0/ipsetting the new IP. But when I run it I got:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "the server rejected our request due to an error in our request",
  "reason": "Invalid",
  "details": {
    
  },
  "code": 422

Can someone help me to figure out what's wrong with my code? I tried a lot of variations using also examples on StackOverflow but no luck.

-- Salvatore D'angelo
kubernetes
kubernetes-apiserver

1 Answer

10/4/2021

After a lot of tries and errors, I found the solution below.

A solution like this is used in Patroni (but there is written in Python) where the Service has one Endpoint that always references the master node. When a failover o switchover occurs the Patroni code update the Service Endpoint. A code like this can be used whenever you have a StatefulSet and you always want to have the Service reference the master node even in a failover scenario.

KUBE_SERVICE_DIR="/var/run/secrets/kubernetes.io/serviceaccount"
KUBE_TOKEN_FILENAME="${KUBE_SERVICE_DIR}/token"
KUBE_CA_CERT="${KUBE_SERVICE_DIR}/ca.crt"
KUBE_TOKEN=$(cat ${KUBE_TOKEN_FILENAME})
KUBERNETES_API_HOST=${KUBERNETES_SERVICE_HOST}
KUBERNETES_API_PORT=${KUBERNETES_SERVICE_PORT}

generatePatchData()
{
  local MASTER_IP=$1
  local MASTER_PORT=$2

  cat <<EOF
{"subsets": [{"addresses": [{"ip": "$MASTER_IP"}], "ports": [{"name": "postgresql", "port": $MASTER_PORT, "protocol": "TCP"}]}]}
EOF
}

patchEndpointIP() {
    local MASTER_IP=$1
    local MASTER_PORT=$2
    curl -XPATCH --cacert ${KUBE_CA_CERT} -H "Content-Type: application/merge-patch+json" -H "Authorization: Bearer ${KUBE_TOKEN}" "https://${KUBERNETES_API_HOST}:${K
UBERNETES_API_PORT}/api/v1/namespaces/cf-db/endpoints/cfdb-ccdb" --data "$(generatePatchData $MASTER_IP $MASTER_PORT)"
}

getEndpointIP() {
    curl -sSk -H "Authorization: Bearer ${KUBE_TOKEN}" "https://${KUBERNETES_API_HOST}:${KUBERNETES_API_PORT}/api/v1/namespaces/cf-db/endpoints/cfdb-ccdb"
}

patchEndpointIP "172.16.140.13" "5431"
getEndpointIP
-- Salvatore D&#39;angelo
Source: StackOverflow