1"use strict";(globalThis.webpackChunkmikes_dev_notebook=globalThis.webpackChunkmikes_dev_notebook||[]).push([[12643],{371220(e,s,a){a.r(s),a.d(s,{assets:()=>o,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"DevOps/Elasticsearch/2022-02-02--elasticsearch-v8-upgrade/index","title":"Performing an Elasticsearch v8 Upgrade","description":"TST, Hong Kong","source":"@site/docs/DevOps/Elasticsearch/2022-02-02--elasticsearch-v8-upgrade/index.md","sourceDirName":"DevOps/Elasticsearch/2022-02-02--elasticsearch-v8-upgrade","slug":"/DevOps/Elasticsearch/2022-02-02--elasticsearch-v8-upgrade/2022-02-02","permalink":"/docs/DevOps/Elasticsearch/2022-02-02--elasticsearch-v8-upgrade/2022-02-02","draft":false,"unlisted":false,"editUrl":"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/DevOps/Elasticsearch/2022-02-02--elasticsearch-v8-upgrade/index.md","tags":[{"inline":true,"label":"LINUX","permalink":"/docs/tags/linux"},{"inline":true,"label":"Elasticsearch","permalink":"/docs/tags/elasticsearch"}],"version":"current","sidebarPosition":7090,"frontMatter":{"sidebar_position":7090,"slug":"2022-02-02","title":"Performing an Elasticsearch v8 Upgrade","authors":"mpolinowski","tags":["LINUX","Elasticsearch"]},"sidebar":"tutorialSidebar","previous":{"title":"Elasticsearch v8, Filebeat (Docker) and NGINX","permalink":"/docs/DevOps/Elasticsearch/2022-02-03--elasticsearch-v8-data-ingestion/2022-02-03"},"next":{"title":"Elastic Filebeat and NGINX Access Logs","permalink":"/docs/DevOps/Elasticsearch/2021-04-01-elastic-filebeats-for-nginx-logs/2021-04-01"}}');var r=a(474848),t=a(28453);const i={sidebar_position:7090,slug:"2022-02-02",title:"Performing an Elasticsearch v8 Upgrade",authors:"mpolinowski",tags:["LINUX","Elasticsearch"]},c=void 0,o={},l=[{value:"Modifications",id:"modifications",level:2},{value:"Blind Dry Run",id:"blind-dry-run",level:2},{value:"Intermediate Version",id:"intermediate-version",level:3},{value:"Change the Kibana User",id:"change-the-kibana-user",level:3},{value:"Create Random User Logins",id:"create-random-user-logins",level:3},{value:"Replace Kibana User Login",id:"replace-kibana-user-login",level:3},{value:"Creating an Anonymous User",id:"creating-an-anonymous-user",level:2}];function d(e){const s={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.p,{children:(0,r.jsx)(s.img,{alt:"TST, Hong Kong",src:a(315811).A+"",width:"1500",height:"547"})}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:(0,r.jsx)(s.a,{href:"#modifications",children:"Modifications"})}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.a,{href:"#blind-dry-run",children:"Blind Dry Run"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:(0,r.jsx)(s.a,{href:"#intermediate-version",children:"Intermediate Version"})}),"\n",(0,r.jsx)(s.li,{children:(0,r.jsx)(s.a,{href:"#change-the-kibana-user",children:"Change the Kibana User"})}),"\n",(0,r.jsx)(s.li,{children:(0,r.jsx)(s.a,{href:"#create-random-user-logins",children:"Create Random User Logins"})}),"\n",(0,r.jsx)(s.li,{children:(0,r.jsx)(s.a,{href:"#replace-kibana-user-login",children:"Replace Kibana User Login"})}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(s.li,{children:(0,r.jsx)(s.a,{href:"#creating-an-anonymous-user",children:"Creating an Anonymous User"})}),"\n"]}),"\n",(0,r.jsxs)(s.p,{children:["I want to upgrade a production instance of Elasticsearch / Kibana ",(0,r.jsx)(s.strong,{children:"v7.16.3"})," to ",(0,r.jsx)(s.strong,{children:"v8.0.0"}),". I am going to use the ",(0,r.jsx)(s.a,{href:"https://github.com/mpolinowski/docker-elk",children:"docker-elk repository"})," as a starting point and add a few little tweaks to it. I will commit the updated version to ",(0,r.jsx)(s.a,{href:"https://github.com/mpolinowski/elk-server-compose",children:"elk-server-compose"}),"."]}),"\n",(0,r.jsx)(s.h2,{id:"modifications",children:"Modifications"}),"\n",(0,r.jsxs)(s.p,{children:["First, I am not going to use Logstash. The service is commented out. If you need to configure Logstash please refer to ",(0,r.jsx)(s.a,{href:"https://github.com/deviantony/docker-elk#configuration",children:"here"}),"."]}),"\n",(0,r.jsxs)(s.p,{children:["Open Elasticsearch for a ",(0,r.jsx)(s.strong,{children:"read-only, anonymous search agent"})," and set ",(0,r.jsx)(s.strong,{children:"CORS"})," to allow everything and ",(0,r.jsx)(s.strong,{children:"deactivate the paid XPACK features"}),":"]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.em,{children:"elasticsearch/config/elasticsearch.yml"})}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-yml",children:'# xpack.license.self_generated.type: trial\r\nxpack.license.self_generated.type: basic\r\nxpack.security.enabled: true\r\nxpack.monitoring.collection.enabled: true\r\nxpack.security.authc:\r\n anonymous:\r\n username: anonymous_user \r\n roles: search_agent\r\n authz_exception: true \r\n\r\n\r\n## CORS\r\nhttp.cors.enabled : true\r\nhttp.cors.allow-origin: "*"\r\nhttp.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETE\r\nhttp.cors.allow-credentials: true\r\nhttp.cors.allow-headers: X-Requested-With, X-Auth-Token, Content-Type, Content-Length, Authorization, Access-Control-Allow-Headers, Accept\n'})}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)(s.strong,{children:"Explanation"}),": My Elasticsearch instance provides full-text search that is accessed from a variety of clients. I do n
1ot want those clients to have to use a user authentication to access the API. And since the request will not only come from a single URL I cannot use CORS to limit access - no matter where the request is coming from the API has to be available. To secure the database I will have to add the ",(0,r.jsx)(s.strong,{children:"search_agent"})," role in Kibana, once the instance is up and running. Users using this role will only have read access to selected indexes."]}),"\n",(0,r.jsx)(s.h2,{id:"blind-dry-run",children:"Blind Dry Run"}),"\n",(0,r.jsxs)(s.p,{children:["Clone the ",(0,r.jsx)(s.a,{href:"https://github.com/mpolinowski/docker-elk",children:"docker-elk repository"})," to a test server and change the ",(0,r.jsx)(s.code,{children:"ELK_VERSION=7.16.3"})," variable in ",(0,r.jsx)(s.code,{children:".env"})," to ",(0,r.jsx)(s.code,{children:"ELK_VERSION=8.0.0"})," and see what happens :)"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"docker-compose build\r\ndocker-compose up\n"})}),"\n",(0,r.jsxs)(s.p,{children:["The instance is coming up but Elasticsearch is exiting complaining that it needs to be updated to version ",(0,r.jsx)(s.strong,{children:"7.17.0"})," before you can go to version ",(0,r.jsx)(s.strong,{children:"8.0.0"}),":"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"elasticsearch_1 | java.lang.IllegalStateException: cannot upgrade a node from version [7.16.3] directly to version [8.0.0], upgrade to version [7.17.0] first.\r\nelasticsearch_1 | at org.elasticsearch.env.NodeMetadata.verifyUpgradeToCurrentVersion(NodeMetadata.java:122)\r\nelasticsearch_1 | at org.elasticsearch.env.NodeEnvironment.checkForIndexCompatibility(NodeEnvironment.java:500)\r\nelasticsearch_1 | at org.elasticsearch.env.NodeEnvironment.upgradeLegacyNodeFolders(NodeEnvironment.java:397)\r\nelasticsearch_1 | at org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:290)\r\nelasticsearch_1 | at org.elasticsearch.node.Node.<init>(Node.java:388)\r\nelasticsearch_1 | at org.elasticsearch.node.Node.<init>(Node.java:277)\r\nelasticsearch_1 | at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:234)\r\nelasticsearch_1 | at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:234)\r\nelasticsearch_1 | at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:358)\r\nelasticsearch_1 | at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:166)\r\nelasticsearch_1 | at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:157)\r\nelasticsearch_1 | at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:77)\r\nelasticsearch_1 | at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:112)\r\nelasticsearch_1 | at org.elasticsearch.cli.Command.main(Command.java:77)\r\nelasticsearch_1 | at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:122)\r\nelasticsearch_1 | at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:80)\r\nelasticsearch_1 | For complete error details, refer to the log at /usr/share/elasticsearch/logs/docker-cluster.lo\r\nwiki_elk-master_elasticsearch_1 exited with code 1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"intermediate-version",children:"Intermediate Version"}),"\n",(0,r.jsxs)(s.p,{children:["So let's change the version to ",(0,r.jsx)(s.code,{children:"ELK_VERSION=7.17.0"})," and re-run:"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"docker-compose build\r\ndocker-compose up\n"})}),"\n",(0,r.jsxs)(s.p,{children:["Everything is working as expected. I am able to create an index. Now I want to see if I can bring this index into ESv8 without breaking anything. So let's change the version back to ",(0,r.jsx)(s.code,{children:"ELK_VERSION=8.0.0"})," and re-run:"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"docker-compose build\r\ndocker-compose up\n"})}),"\n",(0,r.jsx)(s.p,{children:"The instance is coming up again and Elasticsearch is no longer complaining. But I have a new error from Kibana. With version 8 I am no longer allowed to use the default Elasticsearch admin account to connect Kibana to Elasticsearch:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:'kibana_1 | [2022-02-12T13:46:59.393+00:00][FATAL][root] Error: [config validation of [elasticsearch].username]: value of "elastic" is forbidden. This is a superuser account that cannot write to system indices that Kibana needs to function. Use a service account token instead. Learn more: https://www.elastic.co/guide/en/elasticsearch/reference/8.0/service-accounts.html\r\nkibana_1 | [2022-02-12T13:47:28.906+00:00][FATAL][root] Error: [config validation of [elasticsearch].username]: value of "elastic" is forbidden. This is a superuser account that cannot write to system indices that Kibana needs to function. Use a service account token instead. Learn more: https://www.elastic.co/guide/en/elasticsearch/reference/8.0/service-accounts.html\r\nkibana_1 | at ensureValidConfiguration (/usr/share/kibana/src/core/server/config/ensure_valid_configuration.js:25:11)\r\nkibana_1 | at Server.preboot (/usr/share/kibana/src/core/server/server.js:160:5)\r\nkibana_1 | at Root.preboot (/usr/share/kibana/src/core/server/root/index.js:48:14)\r\nkibana_1 | at bootstrap (/usr/share/kibana/src/core/server/bootstrap.js:99:9)\r\nkibana_1 | at Command.<anonymous> (/usr/share/kibana/src/cli/serve/serve.js:216:5)\r\nkibana_1 |\r\nkibana_1 | FATAL Error: [config validation of [elasticsearch].username]: value of "elastic" is forbidden. This is a superuser account that cannot write to system indices that Kibana needs to function. Use a service account token instead. Learn more: https://www.elastic.co/guide/en/elasticsearch/reference/8.0/service-accounts.html\r\nwiki_elk-master_kibana_1 exited
1with code 78\n'})}),"\n",(0,r.jsx)(s.h3,{id:"change-the-kibana-user",children:"Change the Kibana User"}),"\n",(0,r.jsxs)(s.p,{children:["When we are starting the stack for the very first time, we now ",(0,r.jsx)(s.strong,{children:"MUST"})," initialize a password for the built-in ",(0,r.jsx)(s.a,{href:"https://www.elastic.co/guide/en/elasticsearch/reference/current/built-in-users.html",children:"kibana_system user"})," to be able to start and access Kibana. First I need to change the user Kibana is configured to use:"]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.em,{children:"kibana/config/kibana.yml"})}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-yml",children:"## X-Pack security credentials\r\n#\r\nelasticsearch.username: elastic\r\nelasticsearch.password: 'changeme'\n"})}),"\n",(0,r.jsxs)(s.p,{children:["Change the ",(0,r.jsx)(s.code,{children:"elastic"})," user to ",(0,r.jsx)(s.code,{children:"kibana_system"}),":"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-yml",children:"## X-Pack security credentials\r\n#\r\nelasticsearch.username: kibana_system\r\nelasticsearch.password: 'changeme'\n"})}),"\n",(0,r.jsxs)(s.p,{children:["Bringing the cluster back up with ",(0,r.jsx)(s.code,{children:"docker-compose up"})," I can now see that the Error disappeared and was replaced by a warning that the Kibana instances tried to connect but failed:"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:'elasticsearch | {"@timestamp":"2022-02-13T08:12:05.668Z", "log.level": "INFO", "message":"Authentication of [kibana_system] was terminated by realm [reserved] - failed to authenticate user [kibana_system]", "ecs.version": "1.2.0","service.name":"ES_ECS","event.dataset":"elasticsearch.server","process.thread.name":"elasticsearch[63d89c8e892b][system_critical_read][T#1]","log.logger":"org.elasticsearch.xpack.security.authc.RealmsAuthenticator","elasticsearch.cluster.uuid":"6rdcLQTFRmWdJlOQasPOHA","elasticsearch.node.id":"2ybJ-D0PRvOHkklDputWqQ","elasticsearch.node.name":"63d89c8e892b","elasticsearch.cluster.name":"docker-cluster"}\n'})}),"\n",(0,r.jsx)(s.h3,{id:"create-random-user-logins",children:"Create Random User Logins"}),"\n",(0,r.jsxs)(s.p,{children:["Now I can connect to the running Elasticsearch container and generate random passwords for both the ",(0,r.jsx)(s.code,{children:"elastic"})," and ",(0,r.jsx)(s.code,{children:"kibana_system"})," user - ",(0,r.jsx)(s.strong,{children:"Copy those passwords and store them somewhere save"}),"!"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"docker-compose exec -T elasticsearch bin/elasticsearch-reset-password --batch --user elastic\r\n\r\nWARNING: Owner of file [/usr/share/elasticsearch/config/users] used to be [root], but now is [elasticsearch]\r\nWARNING: Owner of file [/usr/share/elasticsearch/config/users_roles] used to be [root], but now is [elasticsearch]\r\nPassword for the [elastic] user successfully reset.\r\nNew value: a1hyme+ry1-AltBfpqxY\n"})}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"docker-compose exec -T elasticsearch bin/elasticsearch-reset-password --batch --user kibana_system\r\n\r\nPassword for the [kibana_system] user successfully reset.\r\nNew value: Fug1bNAI3XJW7UWA5Ahm\n"})}),"\n",(0,r.jsx)(s.h3,{id:"replace-kibana-user-login",children:"Replace Kibana User Login"}),"\n",(0,r.jsxs)(s.p,{children:["Replace the password of the ",(0,r.jsx)(s.code,{children:"kibana_system"})," user inside the Kibana configuration file with the password generated in the previous step:"]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.em,{children:"kibana/config/kibana.yml"})}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-yml",children:"elasticsearch.username: kibana_system\r\nelasticsearch.password: 'Fug1bNAI3XJW7UWA5Ahm'\n"})}),"\n",(0,r.jsxs)(s.p,{children:["And change the ",(0,r.jsx)(s.strong,{children:"ELASTIC_PASSWORD"})," environment variable from the elasticsearch service inside the Compose file ",(0,r.jsx)(s.code,{children:"docker-compose.yml"}),". But it is only used to initialize the keystore during the initial startup of Elasticsearch, and is ignored on subsequent runs:"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-yml",children:"ELASTIC_PASSWORD: 'a1hyme+ry1-AltBfpqxY'\n"})}),"\n",(0,r.jsx)(s.p,{children:"And for another try:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"docker-compose up\n"})}),"\n",(0,r.jsx)(s.p,{children:"A long and exciting log-scroll later I finally read:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:"kibana | [2022-02-13T08:19:21.592+00:00][INFO ][plugins.fleet] Fleet setup completed\r\nkibana | [2022-02-13T08:19:21.598+00:00][INFO ][plugins.securitySolution] Dependent plugin setup complete - Starting ManifestTask\n"})}),"\n",(0,r.jsxs)(s.p,{children:["And I am able to access the Kibana web frontend on port ",(0,r.jsx)(s.code,{children:"5601"})," - use the ",(0,r.jsx)(s.code,{children:"elastic"})," user combined with the generated login. In my case this was ",(0,r.jsx)(s.code,{children:"a1hyme+ry1-AltBfpqxY"}),":"]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.img,{alt:"Elastic Stack v8",src:a(190242).A+"",width:"1050",height:"471"})}),"\n",(0,r.jsx)(s.p,{children:"And to my delight my index was successfully ported to version 8:"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.img,{alt:"Elastic Stack v8",src:a(656825).A+"",width:"1050",height:"417"})}),"\n",(0,r.jsx)(s.h2,{id:"creating-an-anonymous-user",children:"Creating an Anonymous User"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.img,{alt:"Elastic Stack v8",src:a(650576).A+"",width:"1036",height:"235"})}),"\n",(0,r.jsxs)(s.p,{children:["Here I can add the user role ",(0,r.jsx)(s.a,{href:"#modifications",children:"search_agent user role"})," that I added to the ",(0,r.jsx)(s.code,{children:"elasticsearch.yml"})," and enable the read access to my index:"]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.img,{alt:"Elastic Stack v8",src:a(635951).A+"",width:"1038",height:"833"})}),"\n",(0,r.jsxs)(s.p,{children:["I can try accessing the cluster using ",(0,r.jsx)(s.strong,{children:"CURL"}),":"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:'curl -XGET \'http://192.168.2.111:9200/wiki_index/_search?pretty=true&q=9020+Full+HD\'\r\n{\r\n "took" : 34,\r\n "timed_out" : false,\r\n "_shards" : {\r\n "total" : 1,\r\n "successful" : 1,\r\n "skipped" : 0,\r\n "failed" : 0\r\n },\r\n "hits" : {\r\n "total" : {\r\n "value" : 398,\r\n "relation" : "eq"\r\n },\r\n "max_score" : 12.786632,\r\n "hits" : [ ... ]\n'})}),"\n",(0,r.jsx)(s.p,{children:"Success!"})]})}function h(e={}){const{wrapper:s}={...(0,t.R)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},190242(e,s,a){const n=a.p+"assets/images/Elastic_Stack_v8_01-9aac6a436c9a85406e0d2cd2086b3285.png";a.d(s,["A",0,n])},656825(e,s,a){const n=a.p+"assets/images/Elastic_Stack_v8_02-cee61677ef30686abe2e3918f79ed0ff.png";a.d(s,["A",0,n])}
1,650576(e,s,a){const n=a.p+"assets/images/Elastic_Stack_v8_03-0dbd9b09c4f5e581ae741a185d879f20.png";a.d(s,["A",0,n])},635951(e,s,a){const n=a.p+"assets/images/Elastic_Stack_v8_04-6c8d88c68b22b4ed83d70940a3fc6296.png";a.d(s,["A",0,n])},315811(e,s,a){const n=a.p+"assets/images/photo-kt443t6d_64hdh43hfh6dgjdfhg4_d-5124c74efbbadd90a9fcfa6be641f69c.jpg";a.d(s,["A",0,n])},28453(e,s,a){a.d(s,{R:()=>i,x:()=>c});var n=a(296540);const r={},t=n.createContext(r);function i(e){const s=n.useContext(t);return n.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),n.createElement(t.Provider,{value:s},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.