<p>My Hyperledger Fabric network in production runs on Docker swarm, but I want to migrate it to Kubernetes. I have tried searching online but found no resource explaining this process. Is this migration possible? What are the steps involved, and how straightforward would this process be?</p>
<hr />
<p>I have three orderers deployed on three nodes. This is a sample orderer yaml file (I have three):</p>
<pre><code>version: '3.4'

volumes:
  orderer1.mycompany.com:
  
networks:
  dept:
    external:
      name: ar2bc

services:
  dev_orderer1:
    image: hyperledger/fabric-orderer:latest
    environment:
      - ORDERER_GENERAL_LOGLEVEL=INFO
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
      - ORDERER_GENERAL_TLS_ENABLED=true
      - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
      - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: orderer
    volumes:
    - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
    - ./crypto-config/ordererOrganizations/mycompany.com/orderers/orderer1.mycompany.com/msp:/var/hyperledger/orderer/msp
    - ./crypto-config/ordererOrganizations/mycompany.com/orderers/orderer1.mycompany.com/tls/:/var/hyperledger/orderer/tls
    - orderer1.mycompany.com:/var/hyperledger/production/orderer
    deploy:
        mode: replicated
        replicas: 1
        restart_policy:
          condition: on-failure
        placement:
            constraints:
                - node.hostname == node1
    ports:
      - published: 7050
        target: 7050
        mode: host
    networks:
      dept:
        aliases:
          - orderer1.mycompany.com
</code></pre>
<p>I also have three peers deployed on the same three nodes. This is a sample peer yaml file (I have three):</p>
<pre><code>version: '3.4'

volumes:
  peer1.dept.mycompany.com:
  couchdb1.dept.mycompany.com:
  
networks:
  dept:
    external:
      name: ar2bc

services:
  dev_couchdb1:
    image: hyperledger/fabric-couchdb
    environment:
      - COUCHDB_USER= couchdb
      - COUCHDB_PASSWORD=i5pr1nt_c0uchDB
    volumes:
        - couchdb1.dept.mycompany.com:/opt/couchdb/data
    deploy:
        mode: replicated
        replicas: 1
        restart_policy:
          condition: on-failure
        placement:
            constraints:
                - node.hostname == node1
    ports:
     - published: 5984
       target: 5984
       mode: host
    networks:
      dept:
        aliases:
          - couchdb1.dept.mycompany.com

  dev_peer1:
    image: hyperledger/fabric-peer:latest
    environment:
      # couchdb params
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1.dept.mycompany.com:5984
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=couchdb
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=i5pr1nt_c0uchDB
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_PROFILE_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
      - CORE_PEER_ID=peer1.dept.mycompany.com
      - CORE_PEER_ADDRESS=peer1.dept.mycompany.com:7051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer2.dept.mycompany.com:8051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.dept.mycompany.com:7051
      - CORE_PEER_LOCALMSPID=deptMSP
      - CORE_VM_DOCKER_ATTACHSTDOUT=true
      - CORE_CHAINCODE_STARTUPTIMEOUT=1200s
      - CORE_CHAINCODE_EXECUTETIMEOUT=800s
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    volumes:
        - /var/run/:/host/var/run/
        - ./crypto-config/peerOrganizations/dept.mycompany.com/peers/peer1.dept.mycompany.com/msp:/etc/hyperledger/fabric/msp
        - ./crypto-config/peerOrganizations/dept.mycompany.com/peers/peer1.dept.mycompany.com/tls:/etc/hyperledger/fabric/tls
        - peer1.dept.mycompany.com:/var/hyperledger/production
    deploy:
        mode: replicated
        replicas: 1
        restart_policy:
          condition: on-failure
        placement:
            constraints:
                - node.hostname == node1
    ports:
        - published: 7051
          target: 7051
          mode: host
        - published: 7053
          target: 7053
          mode: host
    depends_on:
      - dev_couchdb1
    networks:
      dept:
        aliases:
          - peer1.dept.mycompany.com

  dev_cli1:
    image: hyperledger/fabric-tools:latest
    tty: true
    stdin_open: true
    deploy:
            mode: replicated
            replicas: 1
            restart_policy:
              condition: on-failure
            placement:
                constraints:
                    - node.hostname == node1
    environment:
      - SYS_CHANNEL=ar2dev-syschannel
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_ID=cli
      - CORE_PEER_ADDRESS=peer1.dept.mycompany.com:7051
      - CORE_PEER_LOCALMSPID=deptMSP
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/dept.mycompany.com/peers/peer1.dept.mycompany.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/dept.mycompany.com/peers/peer1.dept.mycompany.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/dept.mycompany.com/peers/peer1.dept.mycompany.com/tls/ca.crt
      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/dept.mycompany.com/users/Admin@dept.mycompany.com/msp
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: /bin/bash
    volumes:
        - /var/run/:/host/var/run/
        - ./chaincode/:/opt/gopath/src/github.com/chaincode
        - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
        - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
    depends_on:
      - dev_peer1
    networks:
      - dept
</code></pre>

user10931326
<p>The process can be really straightforward but it is not possible to avoid the inherent greater complexity of kubernetes (compared to swarm) which results, in turn, to a more complex configuration.</p>
<p>My advise is to start using <a href="https://kompose.io/" rel="nofollow noreferrer"><code>kompose</code> tool</a>, which both gives you the yaml files corresponding to you original docker-compose.yml but also warn you regarding possible issues that may arise.</p>
<p>After following kompose installation steps, naming <code>orderer.yaml</code> your first file and <code>peer.yaml</code> your second file it's only a matter of executing</p>
<pre><code>$ kompose convert -f pathToFile/orderer.yaml --volumes
 hostPath
INFO Service name in docker-compose has been changed from &quot;dev_orderer1&quot; to &quot;dev-orderer1&quot;
INFO Network ar2bc is detected at Source, shall be converted to equivalent NetworkPolicy at Destination
INFO Kubernetes file &quot;dev-orderer1-service.yaml&quot; created
INFO Kubernetes file &quot;dev-orderer1-pod.yaml&quot; created
INFO Kubernetes file &quot;ar2bc-networkpolicy.yaml&quot; created
</code></pre>
<p>and</p>
<pre><code>$ kompose convert -f pathToFile/peer.yaml --volumes hostPath
INFO Service name in docker-compose has been changed from &quot;dev_couchdb1&quot; to &quot;dev-couchdb1&quot;
INFO Service name in docker-compose has been changed from &quot;dev_peer1&quot; to &quot;dev-peer1&quot;
INFO Service name in docker-compose has been changed from &quot;dev_cli1&quot; to &quot;dev-cli1&quot;
INFO Network ar2bc is detected at Source, shall be converted to equivalent NetworkPolicy at Destination
INFO Network ar2bc is detected at Source, shall be converted to equivalent NetworkPolicy at Destination
INFO Network ar2bc is detected at Source, shall be converted to equivalent NetworkPolicy at Destination
INFO Kubernetes file &quot;dev-couchdb1-service.yaml&quot; created
INFO Kubernetes file &quot;dev-peer1-service.yaml&quot; created
INFO Kubernetes file &quot;dev-cli1-pod.yaml&quot; created
INFO Kubernetes file &quot;ar2bc-networkpolicy.yaml&quot; created
INFO Kubernetes file &quot;dev-couchdb1-pod.yaml&quot; created
INFO Kubernetes file &quot;dev-peer1-pod.yaml&quot; created
</code></pre>
<p>and you get new yaml files ready to deploy to kubernetes</p>
<pre><code>$ ls
ar2bc-networkpolicy.yaml  dev-couchdb1-pod.yaml      dev-orderer1-pod.yaml      dev-peer1-pod.yaml
dev-cli1-pod.yaml         dev-couchdb1-service.yaml  dev-orderer1-service.yaml  dev-peer1-service.yaml
</code></pre>
<p>Just to show a little more the result, this is the generated peer1 pod's yaml file</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  annotations:
    kompose.cmd: kompose convert -f peer.yaml --volumes hostPath
    kompose.version: 1.22.0 (955b78124)
  creationTimestamp: null
  labels:
    io.kompose.network/ar2bc: &quot;true&quot;
    io.kompose.service: dev-peer1
  name: dev-peer1
spec:
  containers:
    - args:
        - peer
        - node
        - start
      env:
        - name: CORE_CHAINCODE_EXECUTETIMEOUT
          value: 800s
        - name: CORE_CHAINCODE_STARTUPTIMEOUT
          value: 1200s
        - name: CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS
          value: couchdb1.dept.mycompany.com:5984
        - name: CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
          value: i5pr1nt_c0uchDB
        - name: CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME
          value: couchdb
        - name: CORE_LEDGER_STATE_STATEDATABASE
          value: CouchDB
        - name: CORE_PEER_ADDRESS
          value: peer1.dept.mycompany.com:7051
        - name: CORE_PEER_CHAINCODELISTENADDRESS
          value: 0.0.0.0:7052
        - name: CORE_PEER_GOSSIP_BOOTSTRAP
          value: peer2.dept.mycompany.com:8051
        - name: CORE_PEER_GOSSIP_EXTERNALENDPOINT
          value: peer1.dept.mycompany.com:7051
        - name: CORE_PEER_GOSSIP_ORGLEADER
          value: &quot;false&quot;
        - name: CORE_PEER_GOSSIP_USELEADERELECTION
          value: &quot;true&quot;
        - name: CORE_PEER_ID
          value: peer1.dept.mycompany.com
        - name: CORE_PEER_LOCALMSPID
          value: deptMSP
        - name: CORE_PEER_PROFILE_ENABLED
          value: &quot;true&quot;
        - name: CORE_PEER_TLS_CERT_FILE
          value: /etc/hyperledger/fabric/tls/server.crt
        - name: CORE_PEER_TLS_ENABLED
          value: &quot;true&quot;
        - name: CORE_PEER_TLS_KEY_FILE
          value: /etc/hyperledger/fabric/tls/server.key
        - name: CORE_PEER_TLS_ROOTCERT_FILE
          value: /etc/hyperledger/fabric/tls/ca.crt
        - name: CORE_VM_DOCKER_ATTACHSTDOUT
          value: &quot;true&quot;
        - name: CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE
          value: fabric
        - name: CORE_VM_ENDPOINT
          value: unix:///host/var/run/docker.sock
        - name: FABRIC_LOGGING_SPEC
          value: INFO
      image: hyperledger/fabric-peer:latest
      name: dev-peer1
      ports:
        - containerPort: 7051
        - containerPort: 7053
      resources: {}
      volumeMounts:
        - mountPath: /host/var/run/
          name: dev-peer1-hostpath0
        - mountPath: /etc/hyperledger/fabric/msp
          name: dev-peer1-hostpath1
        - mountPath: /etc/hyperledger/fabric/tls
          name: dev-peer1-hostpath2
        - mountPath: /var/hyperledger/production
          name: peer1.dept.mycompany.com
      workingDir: /opt/gopath/src/github.com/hyperledger/fabric/peer
  nodeSelector:
    kubernetes.io/hostname: node1
  restartPolicy: OnFailure
  volumes:
    - hostPath:
        path: /var/run/
      name: dev-peer1-hostpath0
    - hostPath:
        path: /mnt/c/devenv/src/stackoverflow/66982235-hyperledger-kompose/crypto-config/peerOrganizations/dept.mycompany.com/peers/peer1.dept.mycompany.com/msp
      name: dev-peer1-hostpath1
    - hostPath:
        path: /mnt/c/devenv/src/stackoverflow/66982235-hyperledger-kompose/crypto-config/peerOrganizations/dept.mycompany.com/peers/peer1.dept.mycompany.com/tls
      name: dev-peer1-hostpath2
    - hostPath:
        path: /mnt/c/devenv/src/stackoverflow/66982235-hyperledger-kompose
      name: peer1.dept.mycompany.com
status: {}
</code></pre>
<p>and this is the generated peer1 service's yaml file</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  annotations:
    kompose.cmd: kompose convert -f peer.yaml --volumes hostPath
    kompose.version: 1.22.0 (955b78124)
  creationTimestamp: null
  labels:
    io.kompose.service: dev-peer1
  name: dev-peer1
spec:
  ports:
    - name: &quot;7051&quot;
      port: 7051
      targetPort: 7051
    - name: &quot;7053&quot;
      port: 7053
      targetPort: 7053
  selector:
    io.kompose.service: dev-peer1
status:
  loadBalancer: {}
</code></pre>
<p>To understand which kind of hints kompose is able to give you, please try to run the conversion command without the <code>--volumes hostPath</code> option and you will be given appropriate warnings</p>
<pre><code>$ kompose convert -f pathToFile/orderer.yaml
INFO Service name in docker-compose has been changed from &quot;dev_orderer1&quot; to &quot;dev-orderer1&quot;
WARN Volume mount on the host &quot;/mnt/c/devenv/src/stackoverflow/66982235-hyperledger-kompose/channel-artifacts/genesis.block&quot; isn't supported - ignoring path on the host
WARN Volume mount on the host &quot;/mnt/c/devenv/src/stackoverflow/66982235-hyperledger-kompose/crypto-config/ordererOrganizations/mycompany.com/orderers/orderer1.mycompany.com/msp&quot; isn't supported - ignoring path on the host
WARN Volume mount on the host &quot;/mnt/c/devenv/src/stackoverflow/66982235-hyperledger-kompose/crypto-config/ordererOrganizations/mycompany.com/orderers/orderer1.mycompany.com/tls&quot; isn't supported - ignoring path on the host
INFO Network ar2bc is detected at Source, shall be converted to equivalent NetworkPolicy at Destination
INFO Kubernetes file &quot;dev-orderer1-service.yaml&quot; created
INFO Kubernetes file &quot;dev-orderer1-pod.yaml&quot; created
INFO Kubernetes file &quot;dev-orderer1-claim0-persistentvolumeclaim.yaml&quot; created
INFO Kubernetes file &quot;dev-orderer1-claim1-persistentvolumeclaim.yaml&quot; created
INFO Kubernetes file &quot;dev-orderer1-claim2-persistentvolumeclaim.yaml&quot; created
INFO Kubernetes file &quot;orderer1.mycompany.com-persistentvolumeclaim.yaml&quot; created
INFO Kubernetes file &quot;ar2bc-networkpolicy.yaml&quot; created
</code></pre>
<p>After the conversion of your actual files you can instantiate kubernetes object with</p>
<pre><code>$ kubectl apply -f *.yaml
</code></pre>
<p>or whatever more appropriate command you need (which is not strictly the matter of your question)</p>
