how to convert all kubernetes ingress yamls to use API version networking.k8s.io/v1

12.5k Views Asked by At

Kubernetes Ingress API version networking.k8s.io/v1 has lot of changes in fields wrt extensions/v1beta1 like the following:

* `spec.backend` -> `spec.defaultBackend`
* `serviceName` -> `service.name`
* `servicePort` -> `service.port.name` (for string values)
* `servicePort` -> `service.port.number` (for numeric values)
* `pathType` no longer has a default value in v1; "Exact", "Prefix", or "ImplementationSpecific" must be specified

What is the easiest way to convert all ingress yaml files from extensions/v1beta1 to networking.k8s.io/v1.

Looks like kubectl convert is already deprecated in v1.19.

Kubernetes version:

kubectl version
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.0", GitCommit:"e19964183377d0ec2052d1f1fa930c4d7575bd50", GitTreeState:"clean", BuildDate:"2020-08-26T14:30:33Z", GoVersion:"go1.15", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.0", GitCommit:"e19964183377d0ec2052d1f1fa930c4d7575bd50", GitTreeState:"clean", BuildDate:"2020-08-26T14:23:04Z", GoVersion:"go1.15", Compiler:"gc", Platform:"linux/amd64"}

Error while using kubectl convert:

kubectl convert -f ingress_4_10_1.yaml --output-version  networking.k8s.io/v1
kubectl convert is DEPRECATED and will be removed in a future version.
In order to convert, kubectl apply the object to the cluster, then kubectl get at the desired version.
error: networking.Ingress is not suitable for converting to "networking.k8s.io/v1" in scheme "k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go:30"

My ingress yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: frontend
  annotations:
   kubernetes.io/ingress.class: "ing-class1"
spec:
  rules:
  - host:  frontend.com
    http:
      paths:
      - path: /web-frontend/frontend.php
        backend:
          serviceName: frontend
          servicePort: 80
8

There are 8 best solutions below

0
On

Instead of converting, it could be easier to write it from scratch, using the new schema which can be found in https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource. I rewrote mine, it works. Hope it's helpful.

0
On

convert contains inappropriate dependencies. convert necessarily depends on internal types (in order to convert), but kubectl should not depend on these. In fact, no software outside api server should depend on internal types. The deprecation plan is to create convert as a plugin or separate binary. So the functionality would still exist; just not in kubectl.

Possible options:

  1. Start storing all versions in the cache. Possibly means going back to using disco.ServerResources() instead of disco.ServerPreferredResources() - lookups remain quick. guarantees to work since we have all versions of the object for lookup.

  2. Find a proper way to convert objects using k8s library instead of kubectl convert

  3. Perform a GET against K8s API server using git config version, to perform the conversion.

Take a look: kubectl-convert, kubernetes-release-notes, convert-issues.

0
On

May be you got an answer but it may helpful to others in future. Following configuration is worked for me.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-srv
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: addtest.com
      http:
        paths:
          - path: /add
            pathType: Prefix
            backend:
              service:
                name: add-srv
                port:
                  number: 4000
0
On

I wrote this GIST to do the work for me. Download it and adjust to taste. It's super simple and will do some accidental reformatting based on PyYAML's defaults but at least here it gets the job done.

2
On

It's not that difficult rewrite it by hand, for example:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: frontend
  annotations:
   kubernetes.io/ingress.class: "ing-class1"
spec:
  rules:
  - host: frontend.com
    http:
      paths:
      - backend:
          service:
            name: frontend
            port:
              number: 80
        path: /web-frontend/frontend.php
        pathType: Exact
0
On

I wrote a python script to transform the whole ingress config in case anyone is still looking for that


import yaml
def transform_yaml(file_name):
        with open(file_name, "r") as f:
        data = yaml.safe_load(f)

    for item in data["items"]:
        if item["kind"] == "Ingress" and item["apiVersion"] == "extensions/v1beta1":

            item["apiVersion"] = "networking.k8s.io/v1"

            for rule in item["spec"]["rules"]:
                for path in rule["http"]["paths"]:
                    path["pathType"] = "ImplementationSpecific"

                    backend_data = path.pop("backend")
                    new_backend_data = {
                        "service": {
                            "name": backend_data["serviceName"],
                            "port": {"number": backend_data["servicePort"]},
                        }
                    }
                    path["backend"] = new_backend_data

    with open("transformed_" + file_name, "w") as f:
        yaml.dump(data, f)
0
On

Found a nice summary of the required changes in in https://cloud.google.com/kubernetes-engine/docs/deprecations/apis-1-22#ingress-v122

Field Change
spec.backend Renamed to spec.defaultBackend.
backend serviceName Renamed to service.name.
servicePort Numeric backend servicePort fields are renamed to service.port.number. String backend servicePort fields are renamed to service.port.name.
pathType Now required for each specified path. The value can be: Prefix, Exact, or ImplementationSpecific. To match the undefined v1beta1 behavior, use ImplementationSpecific.
0
On

using kubectl convert --output-version networking.k8s.io/v1

single YAML file

kubectl convert -f app-ingress.yaml --output-version networking.k8s.io/v1 > app-ingress-new.yaml

to convert many files

k8s-ingress-convert.ps1 (Powershell)

Push-Location .

# Without this variable I was seeing
#   Select-String would have file lock (read lock)
#  and rename to -old.yaml would fail.
$ingress_v1beta_list = @(
  Get-ChildItem -Recurse *.yml,*.yaml | 
  Where-Object name -NotLike *-old* | 
  Select-String Ingress -List | 
  ForEach-Object { Select-String -LP $_.Path v1beta } |
  ForEach-Object { $_.path } );

$ingress_v1beta_list

foreach ($ki in $ingress_v1beta_list) {
    Set-Location $ki/.. -Verbose
    $kold=$ki.Replace('.yaml','-old.yaml').Replace('.yml','-old.yml');
    Move-Item $ki $kold -Verbose;
    Write-Warning "k8s converting $ki";
    kubectl convert -f $kold --output-version networking.k8s.io/v1 > $ki
}
Pop-Location

Forward-slash / paths work fine on Win10/Win11 in Powershell. Haven't tested it but might also work on Linux and Mac b/c used forward-slash.

Works best with git and .gitignore

*-old.yaml
*-old.yml