I have a standalone Kubernetes cluster:
plane node - hostname kubernetes1 - 192.168.1.126
work node - hostname kubernetes2 - 192.168.1.138
I deployed this private repository:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
spec:
capacity:
storage: 5Gi # specify your own size
volumeMode: Filesystem
persistentVolumeReclaimPolicy: Retain
local:
path: /opt/registry # can be any path
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- kubernetes2
accessModes:
- ReadWriteMany # only 1 node will read/write on the path.
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv1-claim
spec: # should match specs added in the PersistenVolume
accessModes:
- ReadWriteMany
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: private-repository-k8s
labels:
app: private-repository-k8s
spec:
replicas: 1
selector:
matchLabels:
app: private-repository-k8s
template:
metadata:
labels:
app: private-repository-k8s
spec:
volumes:
- name: certs-vol
hostPath:
path: /opt/certs
type: Directory
- name: task-pv-storage
persistentVolumeClaim:
claimName: pv1-claim # specify the PVC that you've created. PVC and Deployment must be in same namespace.
containers:
- image: registry:2
name: private-repository-k8s
imagePullPolicy: IfNotPresent
env:
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: "/opt/certs/registry.crt"
- name: REGISTRY_HTTP_TLS_KEY
value: "/opt/certs/registry.key"
ports:
- containerPort: 5000
volumeMounts:
- name: certs-vol
mountPath: /opt/certs
- name: task-pv-storage
mountPath: /opt/registry
Service is deployed on the work node:
kubernetes@kubernetes1:/opt/registry$ kubectl get pods
NAME READY STATUS RESTARTS AGE
private-repository-k8s-6d5d954b4f-ldwd6 1/1 Running 0 153m
kubernetes@kubernetes1:/opt/registry$
I tried to create a ingress access because I want to access this pod from the outside:
kubectl create namespace test
service controller:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: test
name: private-repository-service-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: kubernetes2
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: private-repository-service
port:
number: 5000
service-load-balancer:
apiVersion: v1
kind: Service
metadata:
namespace: test
name: private-repository-service
spec:
#type: NodePort
selector:
app: private-repository-k8s
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 5000
targetPort: 5000
# Optional field
# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
#nodePort: 30007
When I run curl 192.168.1.138:5000
there is no response.
Do you know where I might be wrong?
EDIT:
kubernetes@kubernetes1:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d20h
private-registry-service ClusterIP 10.103.148.234 <none> 5000/TCP 6h34m
kubernetes@kubernetes1:~$
Looks like you don't have an ingress-controller of any kind and just want to access the registry directly. In that case you need to create a service of type NodePort
.
apiVersion: v1
kind: Service
metadata:
namespace: test
name: private-repository-service
spec:
type: NodePort # Added
selector:
app: private-repository-k8s
ports:
- port: 5000
targetPort: 5000
nodePort: 30123 # Added
This will bind the service port 5000 to the host's port 30123.
If you run kubectl get svc
this will than give you a slightly different output.
kubernetes@kubernetes1:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d20h
private-registry-service ClusterIP 10.103.148.234 <none> 5000:30123/TCP 6h34m
Notice the mapping 30312:5000
. Now you can send a request to the registry on that port: curl 192.168.1.138:30312
. You can also omit the nodePort
field, kubernetes will then choose a random one in the range between 3000 and 32767 for you. It will be displayed in the kubectl get svc
command as shown above. The Ingress
is not needed and can be removed.
If you want to use an Ingress
as you provided you need to use an ingress-controller, like nginx or traefik, see also kubernetes docs on that topic.
[...] An Ingress controller is responsible for fulfilling the Ingress, usually with a load balancer, though it may also configure your edge router or additional frontends to help handle the traffic.
EDIT
There are a lot of ingress-controllers out there, they all have their advantages and disadvantages. For a beginner, nginx might be a good choise, see docs.
To install it, run these commands (from the install docs page)
$ helm repo add nginx-stable https://helm.nginx.com/stable
$ helm repo update
$ helm install my-release nginx-stable/nginx-ingress
where my-release
is a random name, you can choose what ever you want. This will create an nginx pod in the namespace you installed the chart. It will also create an nginx-ingress service of type LoadBalancer
, like this:
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP
my-release-nginx-ingress LoadBalancer 10.109.27.49 <pending> 80:30536/TCP,443:31694/TCP 111s
As you can see the EXTERNAL-IP
is in <pending>
state. In a public cloud environment like AWS a load-balancer resource like ELB is created and its public ip will be assigned to the service as EXTERNAL-IP
. In your on-premise setup it will stay in <pending>
status. But as you can see, two random node ports are mapped to the http/https ports, like with the nodePort
setup above. Here it's 80 -> 30536 and 433 -> 31694, for you it will be something similar.
Now you can apply your manifests as above. You'll get a service of type ClusterIP
. Also create an Ingress
like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: private-repository-service
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: private-repository-service
port:
number: 5000
Now you can run curl against that host curl -HHost:example.com "http://192.168.1.138:30536/"
(for me it's port 30536, will be a different one for you) and you will get an answer from the registry. Works the same with https using the other port.
Note that I installed everything in the same namespace. In reality you should have a dedicated ingress namespace.
I would also highly recommand to learn the basics of kubernetes, e.g. by a Udemy Course or a youtube tutorail series. If you want to know more about ingress-controller in an on-premise setup, check out my other answer on that topic.