суббота, 6 января 2024 г.

Cilium hubble ui подключение

 Cilium имеет реализацию service-mesh поэтому подключусь к UI интерфейсу (HUBBLE UI), чтобы увидеть и отрассировать связности между контейнерами. В YC есть возможность выбрать cilium как основу для связности в кластере (наряду calico). И наличие cilium позволяет подключать (разносить) ноды (worker and master) по произвольным (разным) L3 сегментам. Важно чтобы трафик пропускался для VXLAN (в принципе, сам VXLAN работает и через 1:1 NAT, возможно и через маскарадинг?) 

Для подключения необходимо установить контейнер HUBBLE UI, ставим манифестом (kubectl apply -f hubble-ui.yaml)

# Source: cilium/templates/hubble-ui-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: "hubble-ui"
  namespace: kube-system
---
# Source: cilium/templates/hubble-ui-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: hubble-ui-envoy
  namespace: kube-system
data:
  envoy.yaml: |
    static_resources:
      listeners:
        - name: listener_hubble_ui
          address:
            socket_address:
              address: 0.0.0.0
              port_value: 8081
          filter_chains:
            - filters:
                - name: envoy.filters.network.http_connection_manager
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                    codec_type: auto
                    stat_prefix: ingress_http
                    route_config:
                      name: local_route
                      virtual_hosts:
                        - name: local_service
                          domains: ["*"]
                          routes:
                            - match:
                                prefix: "/api/"
                              route:
                                cluster: backend
                                prefix_rewrite: "/"
                                timeout: 0s
                                max_stream_duration:
                                  grpc_timeout_header_max: 0s
                            - match:
                                prefix: "/"
                              route:
                                cluster: frontend
                          cors:
                            allow_origin_string_match:
                              - prefix: "*"
                            allow_methods: GET, PUT, DELETE, POST, OPTIONS
                            allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                            max_age: "1728000"
                            expose_headers: grpc-status,grpc-message
                    http_filters:
                      - name: envoy.filters.http.grpc_web
                      - name: envoy.filters.http.cors
                      - name: envoy.filters.http.router
      clusters:
        - name: frontend
          connect_timeout: 0.25s
          type: strict_dns
          lb_policy: round_robin
          load_assignment:
            cluster_name: frontend
            endpoints:
              - lb_endpoints:
                  - endpoint:
                      address:
                        socket_address:
                          address: 127.0.0.1
                          port_value: 8080
        - name: backend
          connect_timeout: 0.25s
          type: logical_dns
          lb_policy: round_robin
          http2_protocol_options: {}
          load_assignment:
            cluster_name: backend
            endpoints:
              - lb_endpoints:
                  - endpoint:
                      address:
                        socket_address:
                          address: 127.0.0.1
                          port_value: 8090
---
# Source: cilium/templates/hubble-ui-clusterrole.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: hubble-ui
rules:
  - apiGroups:
      - networking.k8s.io
    resources:
      - networkpolicies
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - componentstatuses
      - endpoints
      - namespaces
      - nodes
      - pods
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - apiextensions.k8s.io
    resources:
      - customresourcedefinitions
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - cilium.io
    resources:
      - "*"
    verbs:
      - get
      - list
      - watch
---
# Source: cilium/templates/hubble-ui-clusterrolebinding.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: hubble-ui
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: hubble-ui
subjects:
  - kind: ServiceAccount
    namespace: kube-system
    name: "hubble-ui"
---
# Source: cilium/templates/hubble-ui-service.yaml
kind: Service
apiVersion: v1
metadata:
  name: hubble-ui
  labels:
    k8s-app: hubble-ui
  namespace: kube-system
spec:
  selector:
    k8s-app: hubble-ui
  ports:
    - name: http
      port: 80
      targetPort: 8081
  type: ClusterIP
---
# Source: cilium/templates/hubble-ui-deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: kube-system
  labels:
    k8s-app: hubble-ui
  name: hubble-ui
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: hubble-ui
  template:
    metadata:
      annotations:
      labels:
        k8s-app: hubble-ui
    spec:
      securityContext:
        runAsUser: 1001
      serviceAccount: "hubble-ui"
      serviceAccountName: "hubble-ui"
      containers:
        - name: frontend
          image: "quay.io/cilium/hubble-ui:v0.7.9@sha256:e0e461c680ccd083ac24fe4f9e19e675422485f04d8720635ec41f2ba9e5562c"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              name: http
          resources: {}
        - name: backend
          image: "quay.io/cilium/hubble-ui-backend:v0.7.9@sha256:632c938ef6ff30e3a080c59b734afb1fb7493689275443faa1435f7141aabe76"
          imagePullPolicy: IfNotPresent
          env:
            - name: EVENTS_SERVER_PORT
              value: "8090"
            - name: FLOWS_API_ADDR
              value: "hubble-relay:80"
          ports:
            - containerPort: 8090
              name: grpc
          resources: {}
        - name: proxy
          image: "docker.io/envoyproxy/envoy:v1.18.2@sha256:e8b37c1d75787dd1e712ff389b0d37337dc8a174a63bed9c34ba73359dc67da7"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8081
              name: http
          resources: {}
          command: ["envoy"]
          args: ["-c", "/etc/envoy.yaml", "-l", "info"]
          volumeMounts:
            - name: hubble-ui-envoy-yaml
              mountPath: /etc/envoy.yaml
              subPath: envoy.yaml
      volumes:
        - name: hubble-ui-envoy-yaml
          configMap:
            name: hubble-ui-envoy

проверяем что поставилось: 

C:\work\projects>kubectl get deployment -n kube-system

NAME                  READY   UP-TO-DATE   AVAILABLE   AGE

cilium-operator       1/1     1            1           21h

coredns               1/1     1            1           21h

hubble-relay          1/1     1            1           21h

hubble-ui             1/1     1            1           42m

kube-dns-autoscaler   1/1     1            1           21h

metrics-server        1/1     1            1           21h

C:\Users\adm>kubectl get svc -n kube-system

NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE

cilium-agent      ClusterIP   None            <none>        9090/TCP,9095/TCP        21h

cilium-operator   ClusterIP   None            <none>        6942/TCP                 21h

hubble-metrics    ClusterIP   None            <none>        9091/TCP                 21h

hubble-relay      ClusterIP   10.96.212.143   <none>        80/TCP                   21h

hubble-ui         ClusterIP   10.96.42.39     <none>        80/TCP                   45m

kube-dns          ClusterIP   10.96.0.2       <none>        53/UDP,53/TCP,9153/TCP   21h

metrics-server    ClusterIP   10.96.124.89    <none>        443/TCP                  21h

Затем биндим порт командой:

kubectl port-forward -n kube-system svc/hubble-ui 12000:80 

Заходим без авторизации и находим такие визуализации (старые деплойменты надо будет перезапустить, иначе их связностей не будет видно - но они появятся после рестарта)








Разворачивание в кластере кубернетес базы данных postgres и wiki.js

 Разворачиваем через консоль управляемый кластер (master) в яндекс облаке (YC) и сразу добавляем рабочие узлы (worker node(s)). Также, в той же локации (зоне обслуживания ...-a (b,c,d)), добавляем отдельный диск под Persistent Volume (PV), и  запоминаем его "disk-id" Настраиваем локальную работу kubectl по инструкции от яндекс облако.

Затем развернем 2 деплоймента: postgres and wiki.js 

1. Postgres, 

сначала создадим PV и PV Claim (PVC): (pv-pvc.yaml) 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: persistent-volume-pv
  labels:
    type: local
    app: my-database
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: yc-network-hdd # match to disk type in ya cloud
  csi:
    driver: disk-csi-driver.mks.ycloud.io
    fsType: ext4
    volumeHandle: epd6onn7r80053mlt1ad # "Disk-id" from ya cloud
  storageClassName: manual
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-db # will apply to this name of PVC in deployment
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual
  volumeName: persistent-volume-pv

запускаем:  kubectl apply -f .\pv-pvc.yaml

в консоли яндекс клауд должно появиться "Bound" для обоих сущностей (пункт Хранилище)

красным  цветом указано как ссылаются сущности, на зеленый будет ссылка ниже, из деплоймента PG. 

далее разворачиваем еще 2 сущности ConfigMap and Secret (conf-map-sec.yaml)

kind: ConfigMap
apiVersion: v1
metadata:
  name: database-cm
data:
  create-database-table.sql: |
    CREATE TABLE gifts (
      id SERIAL PRIMARY KEY,
      name VARCHAR,
      sold INT
    );

    INSERT INTO gifts (name,sold) VALUES ('Pumpkin', 3000);
    INSERT INTO gifts (name,sold) VALUES ('Christmas Tree', 1000);
    INSERT INTO gifts (name,sold) VALUES ('Socks', 10000);
---
apiVersion: v1
kind: Secret

metadata:
  name: db-secret-credentials
  labels:
    app: my-database
data:
  POSTGRES_DB: Z2lmdHMtdGFibGU= # gifts-table all coded by base64, below too
  POSTGRES_USER: YWRtaW4= # admin
  POSTGRES_PASSWORD: UEBzc3cwcmQ= # P@ssw0rd
 

запускаем:  kubectl apply -f .\conf-map-sec.yaml

ConfigMap здесь только для примера, чтобы понять как могут  передаваться в контейнер файл с нужным содержимым, там можно создать базу, таблицу, внести строки, создать пользователя и т.д. Использовал для проверки работоспособности базы и чтобы потом, подключившись к Pod руками пролить нужные настройки, т.к. пока не изучал как может повлиять многоразовая инициализация рабочей (нужной) базы, которая хранится в отдельном, от кластера кубернетис, диске. Если всё правильно, то должны появиться в секции "Конфигурация" обе сущности с нужными переменными. На белый и светло-коричневый пункты будет ссылка из деплоймента PG

Разворачиваем деплоймент postgres (kubectl apply -f .\depl-pd.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-database
  template:
    metadata:
      labels:
        app: my-database
    spec:
      containers:
        - name: my-database
          image: postgres:latest
          ports:
            - containerPort: 5432
          env:
            - name: POSTGRES_DB
              valueFrom:
                secretKeyRef:
                  name: db-secret-credentials
                  key: POSTGRES_DB

            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: db-secret-credentials
                  key: POSTGRES_USER

            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret-credentials
                  key: POSTGRES_PASSWORD

          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: db-data
              subPath: data

            - mountPath: /docker-entrypoint-initdb.d
              name: postgresdb-loadsql
      volumes:
        - name: postgresdb-loadsql
          configMap:
            name: database-cm

        - name: db-data
          persistentVolumeClaim:
            claimName: pvc-db

Здесь видно, что запрошено (зеленым) PVC который описан ранее, и ему дано имя db-data (голубым) и уже это имя тома/раздела будет подмонтировано к каталогу "/var/lib/postgresql/data" -где лежат сами файлы БД, важно добавить параметр subPath: data

т.к. он указывает и на подкаталоги(?), иначе postgres (PG) находит прежние файлы БД, но считает их чужими, т.к. его конфиг возможно ничего не знает о старой, с параметром же, он находит и конфиг в этом же каталоге и запускается без ошибок. Можно это увидеть в секции "Логи" в YC для данного деплоймента.

Для опубликования внутри кластера порта (5432) для подключения к PG запустим service (svc-db.yaml)

apiVersion: v1
kind: Service
metadata:
  name: svc-db # hostname to connect from app (wiki.js)
  labels:
    app: my-database
spec:
  selector:
    app: my-database
#  type: NodePort
  ports:
  - protocol: TCP
    port: 5432
    targetPort: 5432

запускаем   kubectl apply -f .\svc-db.yaml

Здесь объявлен hostname (светло-бежевым) , который мы укажем в деплойменте wiki.js для подключения к БД.

проверяем:

  C:\work\projects>kubectl get deployments

NAME            READY   UP-TO-DATE   AVAILABLE   AGE

deployment-db   1/1     1            1           106m

C:\work\projects>kubectl get pods

NAME                             READY   STATUS    RESTARTS   AGE

deployment-db-7f9649d79f-65swk   1/1     Running   0          97m

подключаемся к БД и убеждаемся, что БД работает:

C:\work\projects>kubectl exec -it deployment-db-7f9649d79f-65swk -- psql -h localhost -U admin --password -p 5432 gifts-table

Password:

psql (16.1 (Debian 16.1-1.pgdg120+1))

Type "help" for help.

gifts-table=#

Создаем пользователя, базу данных и права для wiki.js (вставляем в промт)

CREATE DATABASE wikijs;

CREATE USER wikijs WITH PASSWORD 'wikijsrocks';

GRANT CONNECT ON DATABASE wikijs TO wikijs;

GRANT USAGE ON SCHEMA public TO wikijs;

GRANT SELECT,UPDATE,INSERT,DELETE ON ALL TABLES IN SCHEMA public TO wikijs;

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO wikijs;

ALTER DATABASE wikijs OWNER TO wikijs;

Выходим из БД и заходим повторно но уже с пользователем wikijs:

kubectl exec -it deployment-db-7f9649d79f-65swk -- psql -h localhost -U wikijs --password -p 5432 wikijs

Должно пустить.


2. Wiki.js

Создаем ConfigMap  (conf-map-sec-wiki-js.yaml)

apiVersion: v1
kind: ConfigMap
metadata:
  name: wikijs
data:
  DB_TYPE: postgres
  DB_HOST: svc-db # hostname from svc-db.yaml
  DB_PORT: "5432"
  DB_NAME: "wikijs"
  DB_USER: "wikijs"
  DB_PASS: "wikijsrocks"

запускам:  kubectl apply -f .\conf-map-sec-wiki-js.yaml

Передаем таким образом параметры в переменные для контейнера с wiki.js 

Создаем деплоймент (и сразу service) для приложения Wiki.js (depl-wiki-js.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wikijs
  name: wikijs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wikijs
  template:
    metadata:
      labels:
        app: wikijs
    spec:
      containers:
        - name: wikijs
          image: 'requarks/wiki:2'
          ports:
            - name: http-3000
              protocol: TCP
              containerPort: 3000
          envFrom:
          - configMapRef:
              name: wikijs
---
apiVersion: v1
kind: Service
metadata:
  name: wikijs
spec:
  selector:
    app: wikijs
  ports:
    - protocol: TCP
      port: 3000
      targetPort: http-3000

Запускаем:  kubectl apply -f .\depl-wiki-js.yaml

Желтым цветом показана привязка к ConfigMap wikijs. В секции "полезная нагрузка" , в соответствующем  деплойменте, провалившись в строку, можно посмотреть "Логи" там должно быть успешное соединение с БД. (используется Deployment c replica=1, но правильно д.б. StatefulSet).

для публикации Wiki.js в интернет понадобится еще один сервис типа loadBalancer 

запускаю его вручную (т.к. это для теста и учебы):

kubectl expose deployment wikijs --type=LoadBalancer --name=my-serv-wiki


Важно, создается новый сервис my-serv-wiki, 

узнаем внешний IP:

 kubectl get services my-serv-wiki

и можно соединяться по 3000 порту  на внешний IP, который виден в выводе комнады.


Замечания:

можно собрать в один файл, но кубернетес нет  команды "depends on:, считается, что все компоненты/сущности, что работают в кубернетес, должно быть толерантны к времени своего запуска/перезапуска.

Деплоймент читает ConfigMap и Secret только один раз, при запуске/перезапуcке, т.е. даже изменив их, надо заставить обновиться Pod-ы (рестарт/scaling и т.д.)


команды для тестирования (kubectl port-forward <pod-name> <localhost-port>:<pod-port>):

kubectl port-forward wikijs-678fdfd978-7tgdj 3000:3000  (прибиндить порт Pod к 127.0.0.1:3000)


ниже полный (по опциям) эквивалент сервиса ...expose ...  LoadBalancer

kubectl expose deployment example --port=8765 --target-port=9376 \
     --name=example-service --type=LoadBalancer



apiVersion: v1
kind: Service
metadata: 
  name: example-service
spec:
  selector:
    app: example
  ports:
    - port: 8765
      targetPort: 9376
  type: LoadBalancer





четверг, 4 января 2024 г.

Get kubernetes dashboard for ya cloud

 Чтобы подключиться к удаленному кластеру (в ya cloud) делаем:

- подключаем локальный (на ноутбуке) kubectl (т.е. добавляем новый контекст в конфиг ~./kube) выполняя команду из меню яндекс менеджмент кластера кубернетис, одноразово,

 что-то типа такого:

 yc managed-kubernetes cluster get-credentials --id catqvqfc0mvgiaq2esiv --external 

это позволит локально управлять через CLI.

ставим сам дашборд:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

чтобы получить дашборд, надо завести пользователя, создаем файл adm.yaml и вносим следующее

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
namespace: kubernetes-dashboard 

затем:  kubectl apply -f adm-kube.yaml   

и даем  ему роль (прописав rbac-kube.yaml) 

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

затем:  kubectl apply -f rbac-kube.yaml 

После чего запрашиваем токен:

kubectl -n kubernetes-dashboard create token admin-user

eyJhbGciOiJSUzI1N................................UheeY0ib_xCB0olUFIH61QXHs3CTZoe-T1j48lSo43g

затем запускаем

kubectl proxy

и переходим по ссылке: 

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

вторник, 24 октября 2023 г.

Отказоустойчивый proxy-cache DNS кластер на Nginx

 Доменные контролеры часто выполняют функцию и корпоративного DNS-сервера, что может привести к их повышенной нагрузке или даже перезагрузке ОС. Но эта роль важна, т.к. при авторизации в домене динамически заводятся  A и PTR записи авторизованных в домене компьютеров и серверов. Для разгрузки AD DC от частых DNS запросов можно использовать кеширующий DNS-сервер (перед ним), но для того, чтобы сам кеш-DNS-сервер не стал точкой отказа, то их надо использовать 2, и для отслеживания их статуса, перед ними поставить UDP прокси-сервер. Проще это сделать на основе связки Nginx c keepalived. Keepalived кроме VRRP функционала должен также отслеживать статуc Nginx за счет постоянного выполнения скрипта (на основе "pidof nginx") или команды (killall -0 nginx) и тот и другой скрипт должны выдавать 0 в RC при наличии процесса.

Также на этих  2-х хостах необходимо установить по экземпляру DNS-cache "unbound" (или другой аналогичный) , который в свою очередь (но намного реже), обращается с DNS запросами к 2-м AD DC серверам.

В первой ноде Nginx  (10.0.0.131) должны быть прописаны, как backend два кэш-сервера:

- 127.0.0.1:53  (экземпляр кеш-сервера на своей же машинке , что и UDP-proxy сервер)

- 10.0.0.132:53  (экземпляр кеш-сервера на другом участнике VRRP кластера)

на втором Nginx (10.0.0.132):

- 127.0.0.1:53  (экземпляр кеш-сервера на своей же машинке , что и UDP-proxy сервер)

- 10.0.0.131:53  (экземпляр кеш-сервера на  другом участнике VRRP кластера)

VIP:10.0.0.130 (важно чтобы frontend слушал только VIP:53, т.к. настоящие IP:53 займет кеширующий сервер на этой  машине)





Cкрипт (на основе "pidof"):
nano /bin/check_nginx.sh
#!/bin/sh
if [ -z "`pidof nginx`" ]; then
  exit 1
fi
chmod 755 /bin/check_nginx.sh

вместо скрипта можно использовать только команду "killall -0 nginx"
тогда скрип с ОС заводить не надо.
=======================
Конфигурация Keepalived:
# (одинаковая для обоих хостов)
нужно проверить/убедиться что включена опция в ядре:
echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.conf && sysctl -p
#
global_defs {
  # Keepalived process identifier
  router_id nginx
}

# Script to check whether Nginx is running or not
vrrp_script check_nginx {
  script "/bin/check_nginx.sh"
  interval 2
}

# Virtual interface - The priority specifies the order in which the assigned interface to take over in a failover
vrrp_instance VI_01 {
  state BACKUP    # if MASTER proirty 120
  interface eth0
  nopreempt 
  virtual_router_id 130
  priority 110

  # The virtual ip address shared between the two NGINX Web Server which will float
  virtual_ipaddress {
    10.0.0.130/24
  }
  track_script {
    check_nginx
  }
}

=============
конфигурация Nginx:
(установка модуля)
yum install nginx-mod-stream

#======

/etc/nginx/nginx.conf
...
events {
worker_connections 1024;
}

stream {
  upstream backends {
    zone   backend 64k;
    server 127.0.0.1:53 fail_timeout=1s;
    server 10.0.0.131:53 fail_timeout=1s;   #for another nginx ip will: 10.0.0.132
  }
  server {
    listen 10.0.0.130:53 udp;
    listen 10.0.0.130:53;  # tcp
    proxy_pass backends;
    proxy_timeout 1s;
    proxy_responses 1;

  }
}

=====
Конфигурация unbound:
(обоих)
...
server:
interface: 127.0.0.1
access-control: 127.0.0.0/8 allow
interface: 10.0.0.131 # for another node 10.0.0.132
access-control: 10.0.0.0/8 allow
        cache-max-ttl: 14400
        cache-min-ttl: 3600
        hide-identity: yes
        hide-version: yes
        minimal-responses: yes
        prefetch: yes
    prefetch-key: yes
    msg-cache-size: 50m
    msg-cache-slabs: 2
    rrset-cache-size: 100m
    rrset-cache-slabs: 2
    key-cache-size: 128m
    key-cache-slabs: 2
    qname-minimisation: yes
...
forward-zone:
  name: "."
  forward-addr: 10.0.0.2
  forward-addr: 10.0.0.3
  forward-first: yes






пятница, 20 октября 2023 г.

Двойной NAT Сisco IOS

Для NAT с подменой source и destination IP на Cisco IOS нужно использовать функционал "ip nat enable" на интерфейсах. Например, чтобы попасть (c IP 10.0.2.158) на 22 порт устройства в "inside" сети  за "inside" интерфейсом (с source IP/net этого "inside" интерфейса  роутера),  обращаясь на виртуальный порт/IP внешнего Outside интерфейса этого роутера, NAT необходимо настроить следующим образом:

interface FastEthernet8
 description
Outside
 ip address 10.129.162.2 255.255.255.240
 ip nat enable
  !
!
interface GigabitEthernet0
 description Inside
 ip address 10.72.1.10 255.255.255.0
 ip nat enable


ip nat source static tcp 10.72.1.1 22 10.129.162.2 443 extendable

ip access-list extended nat
 permit tcp host 10.0.2.158 host 10.129.162.2 eq 443

ip nat source list nat interface GigabitEthernet0 overload

Команда на хосте 10.0.2.158 (который "видит" 10.129.162.2): 
ssh 10.129.162.2 -p 443 
приведет к открытию ssh сессии с 10.0.2.158 на 22-й порт 10.72.1.1 с source  IP: 10.72.1.10 (то есть хосту 10.72.1.1 не нужен маршрут к 10.0.2.158, а достаточно только связности внутри connected сети 10.72.1.0/24.






 



воскресенье, 27 августа 2023 г.

Двойное натирование в Cisco ASA (twice NAT)

Необходимо принять от партнера трафик в р2р линке на виртуальный наш IP (не входит р2р net) с source IP, который тоже не входит р2р сеть, после чего заменить destination и source IP (для доставки уже в своей сети, согласно существующей маршрутизации).


Делаем через ASDM

1) Прописываем маршрутизацию в нужные IP/интерфейсы для всех IP не входящих в р2р сеть (партнера и свой).

2) Заводим объекты "IP" и "сервисы" (типа Net_xxx, TCP_XXX) и настраиваем NAT. Во избежании пересечения NAT с другими, предыдущими трансляциями), максимально конкретизируем в настройках source, dest, service (TCP_port).



3) Очищаем трансляции на этих интерфейсах (обязательно!) командой (можно из ASDM) 

clear xlate interface partner

clear xlate interface inside

вторник, 6 июня 2023 г.

Транзит трафика в Cisco ACI между 2-я L3Out (в одном VRF, но с разным типом маршрутизации.)

 Возникла необходимость пропустить трафик (организовать маршрутизацию) между 2-я L3Out (один с OSPF, другой Static), которые находятся  в одном VRF, но на разных LEAF. Формально  ничего не должно мешать, но при создании контракта в L3Out c OSPF не анонсировался маршрут другого (статического L3Out). Возможно надо было просто включить Route Control Enforcement: "Import":

но в этом L3out уже анонсировались сотни маршрутов и работали сотни сервисов разных арендаторов и десятки ExtEPG (сетей со своими контрактами). И если этот пункт не был отмечен изначально, то сейчас его включать было рискованно для непрерывности трафика.

Необходимая для транзита сеть в ExtEPG в L3Out Static (LEAF_1):




Вариантом (недокументированным?) оказалось создать в L3Out (с OSPF, LEAF_2)  новый ExtEPG-дубликат с сетью  другого ExtEPG из L3Out (Static) (которая должна была бы импортироваться в L3Out с OSPF), но включить только один пункт (!) Export Route Control Subnet:


После этого маршрут из static L3Out появляется на внешнем маршрутизаторе, который связан по  OSPF  (OSPF L3Out). При добавлении контакта трафик начинает ходить.